Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core/SQL] Adds Support for Multiple Mob Pets #6489

Open
wants to merge 1 commit into
base: base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading