Skip to content

Commit

Permalink
Adds Support for Multiple Mob Pets
Browse files Browse the repository at this point in the history
  • Loading branch information
0x05010705 committed Dec 5, 2024
1 parent 6cf8c05 commit 6cc8336
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 45 deletions.
38 changes: 14 additions & 24 deletions scripts/zones/The_Garden_of_RuHmet/mobs/Ixaern_DRG.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@ local ID = zones[xi.zone.THE_GARDEN_OF_RUHMET]
---@type TMobEntity
local entity = {}

entity.onMobSpawn = function(mob)
mob:setLocalVar('petCount', 0)
mob:setLocalVar('petTimer', 0)
end

entity.onMobFight = function(mob, target)
-- Spawn the pets if they are despawned
-- TODO: summon animations?
local mobId = mob:getID()
local x = mob:getXPos()
local y = mob:getYPos()
local z = mob:getZPos()
local petCount = mob:getLocalVar('petCount')
local petTimer = mob:getLocalVar('petTimer')

for i = mobId + 1, mobId + 3 do
local wynav = GetMobByID(i)
if wynav and not wynav:isSpawned() then
local repopWynavs = wynav:getLocalVar('repop') -- see Wynav script
if mob:getBattleTime() - repopWynavs > 10 then
wynav:setSpawn(x + math.random(1, 5), y, z + math.random(1, 5))
wynav:spawn()
wynav:updateEnmity(target)
end
end
if
petCount < 3 and
petTimer < os.time() + 30
then
mob:useMobAbility(xi.jsa.CALL_WYVERN)
mob:setLocalVar('petCount', 3)
mob:setLocalVar('petTimer', os.time())
end
end

Expand All @@ -39,14 +37,6 @@ entity.onMobDeath = function(mob, player, optParams)
end

entity.onMobDespawn = function(mob)
-- despawn pets
local mobId = mob:getID()
for i = mobId + 1, mobId + 3 do
if GetMobByID(i):isSpawned() then
DespawnMob(i)
end
end

-- Pick a new PH for Ix'Aern (DRG)
local groups = ID.mob.AWAERN_DRG_GROUPS
SetServerVariable('[SEA]IxAernDRG_PH', groups[math.random(1, #groups)] + math.random(0, 2))
Expand Down
10 changes: 9 additions & 1 deletion scripts/zones/The_Garden_of_RuHmet/mobs/Ixaern_DRGs_Wynav.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
-- Area: The Garden of Ru'Hmet
-- Mob: Ix'aern DRG's Wynav
-----------------------------------
local ID = zones[xi.zone.THE_GARDEN_OF_RUHMET]
-----------------------------------
---@type TMobEntity
local entity = {}

Expand Down Expand Up @@ -41,7 +43,13 @@ entity.onMobDeath = function(mob, player, optParams)
end

entity.onMobDespawn = function(mob)
mob:setLocalVar('repop', mob:getBattleTime()) -- This get erased on respawn automatic.
local ixaern = GetMobByID(ID.mob.IXAERN_DRG)

if ixaern then
local petCount = ixaern:getLocalVar('petCount')

ixaern:setLocalVar('petCount', petCount - 1)
end
end

return entity
6 changes: 5 additions & 1 deletion sql/mob_pets.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ CREATE TABLE `mob_pets` (
`job` tinyint(4) DEFAULT '9',
`mobname` varchar(24) DEFAULT NULL,
`petname` varchar(24) DEFAULT NULL,
PRIMARY KEY (`mob_mobid`)
PRIMARY KEY (`mob_mobid`, `pet_offset`),
INDEX (`mob_mobid`)
) ENGINE=Aria TRANSACTIONAL=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

Expand Down Expand Up @@ -261,6 +262,9 @@ INSERT INTO `mob_pets` VALUES (16920662,1,14,'Awaern','Aerns_Wynav');
INSERT INTO `mob_pets` VALUES (16920779,1,9,'Awaern','Aerns_Euvhi');
INSERT INTO `mob_pets` VALUES (16920783,1,14,'Awaern','Aerns_Wynav');
INSERT INTO `mob_pets` VALUES (16920787,1,15,'Awaern','Aerns_Elemental');
INSERT INTO `mob_pets` VALUES (16921022,1,14,'Ixaern_DRG','Ixaern_DRGs_Wynav');
INSERT INTO `mob_pets` VALUES (16921022,2,14,'Ixaern_DRG','Ixaern_DRGs_Wynav');
INSERT INTO `mob_pets` VALUES (16921022,3,14,'Ixaern_DRG','Ixaern_DRGs_Wynav');

-- ------------------------------------------------------------
-- Temenos (Zone 37)
Expand Down
29 changes: 22 additions & 7 deletions src/map/ai/controllers/mob_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,21 @@ void CMobController::TryLink()
}
}

// my pet should help as well
if (PMob->PPet != nullptr && PMob->PPet->PAI->IsRoaming())
// my pets should help as well
if (PMob->PPet != nullptr)
{
PMob->PPet->PAI->Engage(PTarget->targid);
CBattleEntity* PPet = PMob->PPet;
// Iterate over all my pets
while (PPet != nullptr)
{
// Check if they are roaming
if (PPet->PAI->IsRoaming())
{
// Have them attack my target
PPet->PAI->Engage(PTarget->targid);
}
PPet = PPet->PPetNext;
}
}

// Handle monster linking if they are close enough
Expand Down Expand Up @@ -1086,12 +1097,16 @@ void CMobController::FollowRoamPath()
PMob->PAI->PathFind->FollowPath(m_Tick);

CBattleEntity* PPet = PMob->PPet;
if (PPet != nullptr && PPet->PAI->IsSpawned() && !PPet->PAI->IsEngaged())
while (PPet != nullptr)
{
// pet should follow me if roaming
position_t targetPoint = nearPosition(PMob->loc.p, 2.1f, (float)M_PI);
if (PPet->PAI->IsSpawned() && !PPet->PAI->IsEngaged())
{
// pet should follow me if roaming
position_t targetPoint = nearPosition(PMob->loc.p, 2.1f, (float)M_PI);

PPet->PAI->PathFind->PathTo(targetPoint);
PPet->PAI->PathFind->PathTo(targetPoint);
}
PPet = PPet->PPetNext;
}

// if I just finished reset my last action time
Expand Down
3 changes: 2 additions & 1 deletion src/map/entities/battleentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,8 @@ class CBattleEntity : public CBaseEntity

CParty* PParty;
CBattleEntity* PPet;
CBattleEntity* PMaster; // Owner/owner of the entity (applies to all combat entities)
CBattleEntity* PPetNext; // Support for multiple pets on same master
CBattleEntity* PMaster; // Owner/owner of the entity (applies to all combat entities)
CBattleEntity* PLastAttacker;
time_point LastAttacked;
battlehistory_t BattleHistory{}; // Stores info related to most recent combat actions taken towards this entity.
Expand Down
25 changes: 16 additions & 9 deletions src/map/lua/lua_baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14632,19 +14632,26 @@ void CLuaBaseEntity::spawnPet(sol::object const& arg0)
return;
}

CMobEntity* PPet = static_cast<CMobEntity*>(PMob->PPet);
CMobEntity* PPetTemp = static_cast<CMobEntity*>(PMob->PPet);

// if a number is given its an avatar or elemental spawn
if ((arg0 != sol::lua_nil) && arg0.is<int>())
while (PPetTemp != nullptr)
{
petutils::SpawnMobPet(PMob, arg0.as<uint32>());
}
CMobEntity* PPet = static_cast<CMobEntity*>(PPetTemp);

// always spawn on master
PPet->m_SpawnPoint = nearPosition(PMob->loc.p, 2.2f, static_cast<float>(M_PI));
// if a number is given its an avatar or elemental spawn
if ((arg0 != sol::lua_nil) && arg0.is<int>())
{
petutils::SpawnMobPet(PMob, arg0.as<uint32>());
}

// setup AI
PPet->Spawn();
// always spawn on master
PPet->m_SpawnPoint = nearPosition(PMob->loc.p, 2.2f, static_cast<float>(M_PI));

// setup AI
PPet->Spawn();

PPetTemp = static_cast<CMobEntity*>(PPetTemp->PPetNext);
}
}
}

Expand Down
22 changes: 20 additions & 2 deletions src/map/utils/zoneutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,10 +635,28 @@ namespace zoneutils
// pet is always spawned by master
PPet->m_AllowRespawn = false;
PPet->m_SpawnType = SPAWNTYPE_SCRIPTED;
PPet->PPetNext = nullptr;
PPet->SetDespawnTime(0s);

PMaster->PPet = PPet;
PPet->PMaster = PMaster;
if (PMaster->PPet == nullptr)
{
PMaster->PPet = PPet;
PPet->PMaster = PMaster;
}
else
{
// We know that PMaster->PPet is not nullptr at least once
// Iterate until we find end of Pet Linked List
CMobEntity* PPetTemp = static_cast<CMobEntity*>(PMaster->PPet);
while (PPetTemp->PPetNext != nullptr)
{
PPetTemp = static_cast<CMobEntity*>(PPetTemp->PPetNext);
}
// Attach the new pet (PPet) to the last pet (PPetTemp)
// Link the new pet to the Master
PPetTemp->PPetNext = PPet;
PPet->PMaster = PMaster;
}
}
}
}
Expand Down

0 comments on commit 6cc8336

Please sign in to comment.