Beispiel #1
0
void CZoneEntities::WideScan(CCharEntity* PChar, uint16 radius)
{
	PChar->pushPacket(new CWideScanPacket(WIDESCAN_BEGIN));
	for (EntityList_t::const_iterator it = m_npcList.begin(); it != m_npcList.end(); ++it)
	{
		CNpcEntity* PNpc = (CNpcEntity*)it->second;
        if (PNpc->status == STATUS_NORMAL && !PNpc->IsNameHidden() && !PNpc->IsUntargetable())
		{
			if (distance(PChar->loc.p, PNpc->loc.p) < radius)
			{
				PChar->pushPacket(new CWideScanPacket(PChar, PNpc));
			}
		}
	}
	for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
	{
		CMobEntity* PMob = (CMobEntity*)it->second;
		if (PMob->status != STATUS_DISAPPEAR && !PMob->IsUntargetable())
		{
			if (distance(PChar->loc.p, PMob->loc.p) < radius)
			{
				PChar->pushPacket(new CWideScanPacket(PChar, PMob));
			}
		}
	}
	PChar->pushPacket(new CWideScanPacket(WIDESCAN_END));
}
Beispiel #2
0
void CZone::FindPartyForMob(CBaseEntity* PEntity)
{
    DSP_DEBUG_BREAK_IF(PEntity == NULL);
    DSP_DEBUG_BREAK_IF(PEntity->objtype != TYPE_MOB);

    CMobEntity* PMob = (CMobEntity*)PEntity;

    // force all mobs in a burning circle to link
    bool forceLink = GetType() == ZONETYPE_BATTLEFIELD || GetType() == ZONETYPE_DYNAMIS || PMob->getMobMod(MOBMOD_SUPERLINK);

    if ((forceLink || PMob->m_Link) && PMob->PParty == NULL)
    {
        for (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it)
        {
            CMobEntity* PCurrentMob = (CMobEntity*)it->second;

            if(!forceLink && !PCurrentMob->m_Link) continue;

            int16 sublink = PMob->getMobMod(MOBMOD_SUBLINK);

            if (forceLink ||
                PCurrentMob->m_Family == PMob->m_Family ||
                sublink && sublink == PCurrentMob->getMobMod(MOBMOD_SUBLINK))
            {

              if(PCurrentMob->PMaster == NULL || PCurrentMob->PMaster->objtype == TYPE_MOB)
              {
                PCurrentMob->PParty->AddMember(PMob);
                return;
              }
            }
        }
        PMob->PParty = new CParty(PMob);
    }
}
    /***************************************************************
        Spawns monsters for the given BCNMID/Battlefield number by
        looking at bcnm_battlefield table for mob ids then spawning
        them and adding them to the monster list for the given
        battlefield.
    ****************************************************************/
    bool spawnMonstersForBcnm(CBattlefield* battlefield) {
        DSP_DEBUG_BREAK_IF(battlefield == nullptr);

        //get ids from DB
        const char* fmtQuery = "SELECT monsterId, conditions \
                            FROM bcnm_battlefield \
                            WHERE bcnmId = %u AND battlefieldNumber = %u";

        int32 ret = Sql_Query(SqlHandle, fmtQuery, battlefield->getID(), battlefield->getBattlefieldNumber());

        if (ret == SQL_ERROR ||
            Sql_NumRows(SqlHandle) == 0)
        {
            ShowError("spawnMonstersForBcnm : SQL error - Cannot find any monster IDs for BCNMID %i Battlefield %i \n",
                battlefield->getID(), battlefield->getBattlefieldNumber());
        }
        else {
            while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) {
                uint32 mobid = Sql_GetUIntData(SqlHandle, 0);
                uint8 condition = Sql_GetUIntData(SqlHandle, 1);
                CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB);
                if (PMob != nullptr)
                {

                    PMob->m_battlefieldID = battlefield->getBattlefieldNumber();
                    PMob->m_bcnmID = battlefield->getID();

                    if (condition & CONDITION_SPAWNED_AT_START)
                    {
                        if (!PMob->PAI->IsSpawned())
                        {
                            PMob->Spawn();

                            //ShowDebug("Spawned %s (%u) id %i inst %i \n",PMob->GetName(),PMob->id,battlefield->getID(),battlefield->getBattlefieldNumber());
                            battlefield->addEnemy(PMob, condition);
                        }
                        else {
                            ShowDebug(CL_CYAN"SpawnMobForBcnm: <%s> (%u) is already spawned\n" CL_RESET, PMob->GetName(), PMob->id);
                        }
                    }
                    else {
                        battlefield->addEnemy(PMob, condition);
                    }
                }
                else {
                    ShowDebug("SpawnMobForBcnm: mob %u not found\n", mobid);
                }
            }
            if (!(battlefield->m_RuleMask & RULES_ALLOW_SUBJOBS))
            {
                // disable players subjob
                battlefield->disableSubJob();
            }
            return true;
        }
        return false;
    }
Beispiel #4
0
void CZoneEntities::HealAllMobs()
{
	for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
	{
		CMobEntity* PCurrentMob = (CMobEntity*)it->second;

		// keep resting until i'm full
		PCurrentMob->Rest(1);
	}
}
Beispiel #5
0
void CMobController::TryLink()
{
    if (PTarget == nullptr)
    {
        return;
    }

    //handle pet behaviour on the targets behalf (faster than in ai_pet_dummy)
    // Avatars defend masters by attacking mobs if the avatar isn't attacking anything currently (bodyguard behaviour)
    if (PTarget->PPet != nullptr && PTarget->PPet->GetBattleTargetID() == 0)
    {
        if (PTarget->PPet->objtype == TYPE_PET && ((CPetEntity*)PTarget->PPet)->getPetType() == PETTYPE_AVATAR)
        {
            petutils::AttackTarget(PTarget, PMob);
        }
    }

    // my pet should help as well
    if (PMob->PPet != nullptr && PMob->PPet->PAI->IsRoaming())
    {
        ((CMobEntity*)PMob->PPet)->PEnmityContainer->AddBaseEnmity(PTarget);
    }

    // Handle monster linking if they are close enough
    if (PMob->PParty != nullptr)
    {
        for (uint16 i = 0; i < PMob->PParty->members.size(); ++i)
        {
            CMobEntity* PPartyMember = (CMobEntity*)PMob->PParty->members[i];

            if (PPartyMember->PAI->IsRoaming() && PPartyMember->CanLink(&PMob->loc.p, PMob->getMobMod(MOBMOD_SUPERLINK)))
            {
                PPartyMember->PEnmityContainer->AddBaseEnmity(PTarget);

                if (PPartyMember->m_roamFlags & ROAMFLAG_IGNORE)
                {
                    // force into attack action
                    //#TODO
                    PPartyMember->PAI->Engage(PTarget->targid);
                }
            }
        }
    }

    // ask my master for help
    if (PMob->PMaster != nullptr && PMob->PMaster->PAI->IsRoaming())
    {
        CMobEntity* PMaster = (CMobEntity*)PMob->PMaster;

        if (PMaster->PAI->IsRoaming() && PMaster->CanLink(&PMob->loc.p, PMob->getMobMod(MOBMOD_SUPERLINK)))
        {
            PMaster->PEnmityContainer->AddBaseEnmity(PTarget);
        }
    }
}
Beispiel #6
0
void CMobEntity::Spawn()
{
    CBattleEntity::Spawn();
    m_giveExp = true;
    m_HiPCLvl = 0;
    m_THLvl = 0;
    m_ItemStolen = false;
    m_DropItemTime = 1000;
    animationsub = getMobMod(MOBMOD_SPAWN_ANIMATIONSUB);
    CallForHelp(false);

    PEnmityContainer->Clear();

    uint8 level = m_minLevel;

    // Generate a random level between min and max level
    if (m_maxLevel != m_minLevel)
    {
        level += dsprand::GetRandomNumber(0, m_maxLevel - m_minLevel);
    }

    SetMLevel(level);
    SetSLevel(level);//calculated in function
    delRageMode();

    mobutils::CalculateStats(this);
    mobutils::GetAvailableSpells(this);

    // spawn somewhere around my point
    loc.p = m_SpawnPoint;

    if (m_roamFlags & ROAMFLAG_STEALTH)
    {
        HideName(true);
        Untargetable(true);
    }

    // add people to my posse
    if (getMobMod(MOBMOD_ASSIST))
    {
        for (int8 i = 1; i < getMobMod(MOBMOD_ASSIST) + 1; i++)
        {
            CMobEntity* PMob = (CMobEntity*)GetEntity(targid + i, TYPE_MOB);

            if (PMob != nullptr)
            {
                PMob->setMobMod(MOBMOD_SUPERLINK, targid);
            }
        }
    }
    
    m_DespawnTimer = time_point::min();
    luautils::OnMobSpawn(this);
}
Beispiel #7
0
void CZone::SpawnMOBs(CCharEntity* PChar)
{
	for (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it)
	{
		CMobEntity* PCurrentMob = (CMobEntity*)it->second;
        SpawnIDList_t::iterator MOB = PChar->SpawnMOBList.lower_bound(PCurrentMob->id);

		float CurrentDistance = distance(PChar->loc.p, PCurrentMob->loc.p);

		if (PCurrentMob->status == STATUS_UPDATE &&
			CurrentDistance < 50)
		{
			if( MOB == PChar->SpawnMOBList.end() ||
				PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first))
			{
				PChar->SpawnMOBList.insert(MOB, SpawnIDList_t::value_type(PCurrentMob->id, PCurrentMob));
				PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob, ENTITY_SPAWN));
			}

			if (PChar->isDead() || PChar->nameflags.flags & FLAG_GM || PCurrentMob->PMaster != NULL)
				continue;

        // проверка ночного/дневного сна монстров уже учтена в проверке CurrentAction, т.к. во сне монстры не ходят ^^

        uint16 expGain = (uint16)charutils::GetRealExp(PChar->GetMLevel(),PCurrentMob->GetMLevel());

        CAIMobDummy* PAIMob = (CAIMobDummy*)PCurrentMob->PBattleAI;

        bool validAggro = expGain > 50 || PChar->animation == ANIMATION_HEALING || PCurrentMob->getMobMod(MOBMOD_ALWAYS_AGGRO);

        if(validAggro && PAIMob->CanAggroTarget(PChar))
        {
          PCurrentMob->PEnmityContainer->AddBaseEnmity(PChar);
        }

  		}
      else
      {
			if( MOB != PChar->SpawnMOBList.end() &&
			  !(PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first)))
			{
				PChar->SpawnMOBList.erase(MOB);
				PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob,ENTITY_DESPAWN));
			}
		}
	}
}
Beispiel #8
0
void CZoneEntities::SpawnMOBs(CCharEntity* PChar)
{
    for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
    {
        CMobEntity* PCurrentMob = (CMobEntity*)it->second;
        SpawnIDList_t::iterator MOB = PChar->SpawnMOBList.lower_bound(PCurrentMob->id);

        float CurrentDistance = distance(PChar->loc.p, PCurrentMob->loc.p);

        if (PCurrentMob->status != STATUS_DISAPPEAR &&
            CurrentDistance < 50)
        {
            if (MOB == PChar->SpawnMOBList.end() ||
                PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first))
            {
                PChar->SpawnMOBList.insert(MOB, SpawnIDList_t::value_type(PCurrentMob->id, PCurrentMob));
                PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob, ENTITY_SPAWN, UPDATE_ALL_MOB));
            }

            if (PChar->isDead() || PChar->nameflags.flags & FLAG_GM || PCurrentMob->PMaster != nullptr)
                continue;

            // проверка ночного/дневного сна монстров уже учтена в проверке CurrentAction, т.к. во сне монстры не ходят ^^

            uint16 expGain = (uint16)charutils::GetRealExp(PChar->GetMLevel(), PCurrentMob->GetMLevel());

            CMobController* PController = static_cast<CMobController*>(PCurrentMob->PAI->GetController());

            bool validAggro = expGain > 50 || PChar->isSitting() || PCurrentMob->getMobMod(MOBMOD_ALWAYS_AGGRO);

            if (validAggro && PController->CanAggroTarget(PChar))
            {
                PCurrentMob->PEnmityContainer->AddBaseEnmity(PChar);
            }
        }
        else
        {
            if (MOB != PChar->SpawnMOBList.end() &&
                !(PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first)))
            {
                PChar->SpawnMOBList.erase(MOB);
                PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob, ENTITY_DESPAWN, UPDATE_NONE));
            }
        }
    }
}
    bool spawnSecondPartDynamis(CBattlefield* battlefield) {
        DSP_DEBUG_BREAK_IF(battlefield == nullptr);

        //get ids from DB
        const int8* fmtQuery = "SELECT monsterId \
								FROM bcnm_battlefield \
								WHERE bcnmId = %u AND battlefieldNumber = 2";

        int32 ret = Sql_Query(SqlHandle, fmtQuery, battlefield->getID());

        if (ret == SQL_ERROR ||
            Sql_NumRows(SqlHandle) == 0)
        {
            ShowError("spawnSecondPartDynamis : SQL error - Cannot find any monster IDs for Dynamis %i \n",
                battlefield->getID(), battlefield->getBattlefieldNumber());
        }
        else {
            while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) {
                uint32 mobid = Sql_GetUIntData(SqlHandle, 0);
                CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB);
                if (PMob != nullptr)
                {
                    if (!PMob->PAI->IsSpawned())
                    {
                        PMob->Spawn();

                        PMob->m_battlefieldID = battlefield->getBattlefieldNumber();

                        ShowDebug("Spawned %s (%u) id %i inst %i \n", PMob->GetName(), PMob->id, battlefield->getID(), battlefield->getBattlefieldNumber());
                        battlefield->addEnemy(PMob, CONDITION_SPAWNED_AT_START & CONDITION_WIN_REQUIREMENT);
                    }
                    else {
                        ShowDebug(CL_CYAN"spawnSecondPartDynamis: <%s> (%u) is already spawned\n" CL_RESET, PMob->GetName(), PMob->id);
                    }
                }
                else {
                    ShowDebug("spawnSecondPartDynamis: mob %u not found\n", mobid);
                }
            }
            return true;
        }
        return false;
    }
Beispiel #10
0
	bool spawnSecondPartDynamis(CInstance* instance){
		DSP_DEBUG_BREAK_IF(instance==NULL);

		//get ids from DB
		const int8* fmtQuery = "SELECT monsterId \
								FROM bcnm_instance \
								WHERE bcnmId = %u AND instanceNumber = 2";

		int32 ret = Sql_Query(SqlHandle, fmtQuery, instance->getID());

		if (ret == SQL_ERROR ||
			Sql_NumRows(SqlHandle) == 0)
		{
			ShowError("spawnSecondPartDynamis : SQL error - Cannot find any monster IDs for Dynamis %i \n",
				instance->getID(), instance->getInstanceNumber());
		}
		else{
			while(Sql_NextRow(SqlHandle) == SQL_SUCCESS){
				uint32 mobid = Sql_GetUIntData(SqlHandle,0);
				CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB);
				if (PMob != NULL)
				{
				    if (PMob->PBattleAI->GetCurrentAction() == ACTION_NONE ||
				        PMob->PBattleAI->GetCurrentAction() == ACTION_SPAWN)
				    {
				        PMob->PBattleAI->SetLastActionTime(0);
				        PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);

						PMob->m_instanceID = instance->getInstanceNumber();

						ShowDebug("Spawned %s (%u) id %i inst %i \n",PMob->GetName(),PMob->id,instance->getID(),instance->getInstanceNumber());
						instance->addEnemy(PMob, CONDITION_SPAWNED_AT_START & CONDITION_WIN_REQUIREMENT);
				    } else {
				        ShowDebug(CL_CYAN"spawnSecondPartDynamis: <%s> (%u) is alredy spawned\n" CL_RESET, PMob->GetName(), PMob->id);
				    }
				} else {
				    ShowDebug("spawnSecondPartDynamis: mob %u not found\n", mobid);
				}
			}
			return true;
		}
		return false;
	}
Beispiel #11
0
void SpawnCatch(CCharEntity* PChar, uint32 mobid)
	{
		CBattleEntity* TargetID = (CBattleEntity*)PChar;
		CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB);
		
		if (PMob->PBattleAI->GetCurrentAction() == ACTION_NONE)
		{
			PMob->SetDespawnTimer(3);
			PMob->m_AllowRespawn = false;
			PMob->m_Type = MOBTYPE_FISHED;
			PMob->CanDetectTarget(TargetID, true);
			PMob->m_Behaviour = BEHAVIOUR_NO_TURN;
			PMob->m_SpawnPoint = nearPosition(PChar->loc.p, 2.2f, M_PI);
			PMob->PBattleAI->SetLastActionTime(gettick());
			PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);
			PMob->PBattleAI->CheckCurrentAction(gettick());
			PMob->PEnmityContainer->AddBaseEnmity(TargetID);
		}

	}
Beispiel #12
0
void CZoneEntities::WeatherChange(WEATHER weather)
{
    auto element = zoneutils::GetWeatherElement(weather);
    for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
    {
        CMobEntity* PCurrentMob = (CMobEntity*)it->second;

        PCurrentMob->PAI->EventHandler.triggerListener("WEATHER_CHANGE", PCurrentMob, static_cast<int>(weather), element);
        // can't detect by scent in this weather
        if (PCurrentMob->m_Aggro & AGGRO_SCENT)
        {
            PCurrentMob->m_disableScent = (weather == WEATHER_RAIN || weather == WEATHER_SQUALL || weather == WEATHER_BLIZZARDS);
        }

        if (PCurrentMob->m_EcoSystem == SYSTEM_ELEMENTAL && PCurrentMob->PMaster == nullptr && PCurrentMob->m_SpawnType == SPAWNTYPE_WEATHER)
        {
            if (PCurrentMob->m_Element == element)
            {
                PCurrentMob->SetDespawnTime(0s);
                PCurrentMob->m_AllowRespawn = true;
                PCurrentMob->Spawn();
            }
            else
            {
                PCurrentMob->SetDespawnTime(1s);
                PCurrentMob->m_AllowRespawn = false;
            }
        }
        else if (PCurrentMob->m_SpawnType == SPAWNTYPE_FOG)
        {
            if (weather == WEATHER_FOG)
            {
                PCurrentMob->SetDespawnTime(0s);
                PCurrentMob->m_AllowRespawn = true;
                PCurrentMob->Spawn();
            }
            else
            {
                PCurrentMob->SetDespawnTime(1s);
                PCurrentMob->m_AllowRespawn = false;
            }
        }
    }

    for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
    {
        CCharEntity* PChar = (CCharEntity*)it->second;

        PChar->PLatentEffectContainer->CheckLatentsZone();
        PChar->PAI->EventHandler.triggerListener("WEATHER_CHANGE", PChar, static_cast<int>(weather), element);
    }
}
Beispiel #13
0
void CZoneEntities::TOTDChange(TIMETYPE TOTD)
{
	SCRIPTTYPE ScriptType = SCRIPT_NONE;

	switch (TOTD)
	{
		case TIME_MIDNIGHT:
		{

		}
		break;
		case TIME_NEWDAY:
		{
			for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
			{
				CMobEntity* PMob = (CMobEntity*)it->second;

				if (PMob->m_SpawnType == SPAWNTYPE_ATNIGHT)
				{
					PMob->SetDespawnTimer(1);
					PMob->m_AllowRespawn = false;
				}
			}
		}
		break;
		case TIME_DAWN:
		{
			ScriptType = SCRIPT_TIME_DAWN;

			for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
			{
				CMobEntity* PMob = (CMobEntity*)it->second;

				if (PMob->m_SpawnType == SPAWNTYPE_ATEVENING)
				{
					PMob->SetDespawnTimer(1);
					PMob->m_AllowRespawn = false;
				}
			}
		}
		break;
		case TIME_DAY:
		{
			ScriptType = SCRIPT_TIME_DAY;
		}
		break;
		case TIME_DUSK:
		{
			ScriptType = SCRIPT_TIME_DUSK;
		}
		break;
		case TIME_EVENING:
		{
			ScriptType = SCRIPT_TIME_EVENING;

			for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
			{
				CMobEntity* PMob = (CMobEntity*)it->second;

				if (PMob->m_SpawnType == SPAWNTYPE_ATEVENING)
				{
					PMob->SetDespawnTimer(0);
					PMob->m_AllowRespawn = true;
					PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);
				}
			}
		}
		break;
		case TIME_NIGHT:
		{
			for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
			{
				CMobEntity* PMob = (CMobEntity*)it->second;

				if (PMob->m_SpawnType == SPAWNTYPE_ATNIGHT)
				{
					PMob->SetDespawnTimer(0);
					PMob->m_AllowRespawn = true;
					PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);
				}
			}
		}
		break;
	}
	if (ScriptType != SCRIPT_NONE)
	{
		for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
		{
			charutils::CheckEquipLogic((CCharEntity*)it->second, ScriptType, TOTD);
		}
	}
}
Beispiel #14
0
void CZoneEntities::DecreaseZoneCounter(CCharEntity* PChar)
{
    DSP_DEBUG_BREAK_IF(PChar == nullptr);
    DSP_DEBUG_BREAK_IF(PChar->loc.zone != m_zone);

    //remove pets
    if (PChar->PPet != nullptr)
    {
        charutils::BuildingCharPetAbilityTable(PChar, (CPetEntity*)PChar->PPet, 0);//blank the pet commands
        if (PChar->PPet->isCharmed) {
            petutils::DespawnPet(PChar);
        }
        else {
            PChar->PPet->status = STATUS_DISAPPEAR;
            if (((CPetEntity*)(PChar->PPet))->getPetType() == PETTYPE_AVATAR)
                PChar->setModifier(MOD_AVATAR_PERPETUATION, 0);
        }
        // It may have been nullptred by DespawnPet
        if (PChar->PPet != nullptr) {
            PChar->PPet->PAI->Disengage();

            for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
            {
                //inform other players of the pets removal
                CCharEntity* PCurrentChar = (CCharEntity*)it->second;
                SpawnIDList_t::iterator PET = PCurrentChar->SpawnPETList.find(PChar->PPet->id);

                if (PET != PCurrentChar->SpawnPETList.end())
                {
                    PCurrentChar->SpawnPETList.erase(PET);
                    PCurrentChar->pushPacket(new CEntityUpdatePacket(PChar->PPet, ENTITY_DESPAWN, UPDATE_NONE));
                }
            }
            PChar->PPet = nullptr;
        }
    }

    //remove bcnm status
    if (m_zone->m_BattlefieldHandler != nullptr && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_BATTLEFIELD))
    {
        if (m_zone->m_BattlefieldHandler->disconnectFromBcnm(PChar)) {
            ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n", PChar->GetName());
        }

        if (PChar->loc.destination == 0) { //this player is disconnecting/logged out, so move them to the entrance
            //move depending on zone
            int pos[4] = {0, 0, 0, 0};
            battlefieldutils::getStartPosition(m_zone->GetID(), pos);
            if (pos != nullptr) {
                PChar->loc.p.x = pos[0];
                PChar->loc.p.y = pos[1];
                PChar->loc.p.z = pos[2];
                PChar->loc.p.rotation = pos[3];
                PChar->updatemask |= UPDATE_POS;
                charutils::SaveCharPosition(PChar);
            }
            else {
                ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n", PChar->GetName());
            }
        }
    }
    else if (m_zone->m_BattlefieldHandler != nullptr && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DYNAMIS, 0))
    {
        if (m_zone->m_BattlefieldHandler->disconnectFromDynamis(PChar)) {
            ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n", PChar->GetName());
        }

        if (PChar->loc.destination == 0) { //this player is disconnecting/logged out, so move them to the entrance
            //move depending on zone
            int pos[4] = {0, 0, 0, 0};
            battlefieldutils::getStartPosition(m_zone->GetID(), pos);
            if (!(pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0)) {
                PChar->loc.p.x = pos[0];
                PChar->loc.p.y = pos[1];
                PChar->loc.p.z = pos[2];
                PChar->loc.p.rotation = pos[3];
                PChar->updatemask |= UPDATE_POS;
                charutils::SaveCharPosition(PChar);
            }
            else {
                ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n", PChar->GetName());
            }
        }
    }

    for (auto PMobIt : m_mobList)
    {
        CMobEntity* PCurrentMob = (CMobEntity*)PMobIt.second;
        PCurrentMob->PEnmityContainer->LogoutReset(PChar->id);
        if (PCurrentMob->m_OwnerID.id == PChar->id)
        {
            PCurrentMob->m_OwnerID.clean();
            PCurrentMob->updatemask |= UPDATE_STATUS;
        }
        if (PCurrentMob->GetBattleTargetID() == PChar->targid)
        {
            PCurrentMob->SetBattleTargetID(0);
        }
    }

    if (PChar->animation == ANIMATION_SYNTH)
    {
        PChar->CraftContainer->setQuantity(0, synthutils::SYNTHESIS_FAIL);
        synthutils::sendSynthDone(PChar);
    }

    // TODO: могут возникать проблемы с переходом между одной и той же зоной (zone == prevzone)

    m_charList.erase(PChar->targid);

    ShowDebug(CL_CYAN"CZone:: %s DecreaseZoneCounter <%u> %s\n" CL_RESET, m_zone->GetName(), m_charList.size(), PChar->GetName());
}
Beispiel #15
0
void SpawnMobPet(CBattleEntity* PMaster, uint32 PetID)
{
	// this is ONLY used for mob smn elementals / avatars
	/*
	This should eventually be merged into one big spawn pet method.
	At the moment player pets and mob pets are totally different. We need a central place
	to manage pet families and spawn them.
	*/

	// grab pet info
	Pet_t* petData = g_PPetList.at(PetID);
	CMobEntity* PPet = (CMobEntity*)PMaster->PPet;

	PPet->look = petData->look;
	PPet->name = petData->name;
	PPet->m_EcoSystem = petData->EcoSystem;
	PPet->m_Family = petData->m_Family;
	PPet->m_Element = petData->m_Element;
	PPet->HPscale = petData->HPscale;
	PPet->MPscale = petData->MPscale;
	PPet->m_HasSpellScript = petData->hasSpellScript;

    // assuming elemental spawn
    PPet->setModifier(MOD_DMGPHYS,-50); //-50% PDT

	PPet->m_SpellListContainer = mobSpellList::GetMobSpellList(petData->spellList);

	PPet->setModifier(MOD_SLASHRES, petData->slashres);
	PPet->setModifier(MOD_PIERCERES,petData->pierceres);
	PPet->setModifier(MOD_HTHRES, petData->hthres);
	PPet->setModifier(MOD_IMPACTRES, petData->impactres);

    PPet->setModifier(MOD_FIREDEF,    petData->firedef); // These are stored as floating percentages
    PPet->setModifier(MOD_ICEDEF,     petData->icedef); // and need to be adjusted into modifier units.
    PPet->setModifier(MOD_WINDDEF,    petData->winddef); // Higher DEF = lower damage.
    PPet->setModifier(MOD_EARTHDEF,   petData->earthdef); // Negatives signify increased damage.
    PPet->setModifier(MOD_THUNDERDEF, petData->thunderdef); // Positives signify reduced damage.
    PPet->setModifier(MOD_WATERDEF,   petData->waterdef); // Ex: 125% damage would be 1.25, 50% damage would be 0.50
    PPet->setModifier(MOD_LIGHTDEF,   petData->lightdef); // (1.25 - 1) * -1000 = -250 DEF
    PPet->setModifier(MOD_DARKDEF,    petData->darkdef); // (0.50 - 1) * -1000 = 500 DEF

    PPet->setModifier(MOD_FIRERES,    petData->fireres); // These are stored as floating percentages
    PPet->setModifier(MOD_ICERES,     petData->iceres); // and need to be adjusted into modifier units.
    PPet->setModifier(MOD_WINDRES,    petData->windres); // Higher RES = lower damage.
    PPet->setModifier(MOD_EARTHRES,   petData->earthres); // Negatives signify lower resist chance.
    PPet->setModifier(MOD_THUNDERRES, petData->thunderres); // Positives signify increased resist chance.
    PPet->setModifier(MOD_WATERRES,   petData->waterres);
    PPet->setModifier(MOD_LIGHTRES,   petData->lightres);
    PPet->setModifier(MOD_DARKRES,    petData->darkres);
}
Beispiel #16
0
CMobEntity* InstantiateAlly(uint32 groupid, uint16 zoneID, CInstance* instance)
{
	const char* Query =
		"SELECT zoneid, name, \
		respawntime, spawntype, dropid, mob_groups.HP, mob_groups.MP, minLevel, maxLevel, \
		modelid, mJob, sJob, cmbSkill, cmbDmgMult, cmbDelay, behavior, links, mobType, immunity, \
		systemid, mobsize, speed, \
		STR, DEX, VIT, AGI, `INT`, MND, CHR, EVA, DEF, \
		Slash, Pierce, H2H, Impact, \
		Fire, Ice, Wind, Earth, Lightning, Water, Light, Dark, Element, \
		mob_pools.familyid, name_prefix, entityFlags, animationsub, \
		(mob_family_system.HP / 100), (mob_family_system.MP / 100), hasSpellScript, spellList, ATT, ACC, mob_groups.poolid, \
		allegiance, namevis, aggro, mob_pools.skill_list_id, mob_pools.true_detection, mob_family_system.detects, packet_name \
		FROM mob_groups INNER JOIN mob_pools ON mob_groups.poolid = mob_pools.poolid \
		INNER JOIN mob_family_system ON mob_pools.familyid = mob_family_system.familyid \
		WHERE mob_groups.groupid = %u";

	int32 ret = Sql_Query(SqlHandle, Query, groupid);

	CMobEntity* PMob = nullptr;

	if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0)
	{
		if (Sql_NextRow(SqlHandle) == SQL_SUCCESS)
		{
			PMob = new CMobEntity;
            PMob->PInstance = instance;

			PMob->name.insert(0, (const char*)Sql_GetData(SqlHandle, 1));
            PMob->packetName.insert(0, (const char*)Sql_GetData(SqlHandle, 61));

			PMob->m_RespawnTime = Sql_GetUIntData(SqlHandle, 2) * 1000;
			PMob->m_SpawnType = (SPAWNTYPE)Sql_GetUIntData(SqlHandle, 3);
			PMob->m_DropID = Sql_GetUIntData(SqlHandle, 4);

			PMob->HPmodifier = (uint32)Sql_GetIntData(SqlHandle, 5);
			PMob->MPmodifier = (uint32)Sql_GetIntData(SqlHandle, 6);

			PMob->m_minLevel = (uint8)Sql_GetIntData(SqlHandle, 7);
			PMob->m_maxLevel = (uint8)Sql_GetIntData(SqlHandle, 8);

			memcpy(&PMob->look, Sql_GetData(SqlHandle, 9), 23);

			PMob->SetMJob(Sql_GetIntData(SqlHandle, 10));
			PMob->SetSJob(Sql_GetIntData(SqlHandle, 11));

			PMob->m_Weapons[SLOT_MAIN]->setMaxHit(1);
			PMob->m_Weapons[SLOT_MAIN]->setSkillType(Sql_GetIntData(SqlHandle, 12));
			PMob->m_dmgMult = Sql_GetUIntData(SqlHandle, 13);
			PMob->m_Weapons[SLOT_MAIN]->setDelay((Sql_GetIntData(SqlHandle, 14) * 1000) / 60);
			PMob->m_Weapons[SLOT_MAIN]->setBaseDelay((Sql_GetIntData(SqlHandle, 14) * 1000) / 60);

			PMob->m_Behaviour = (uint16)Sql_GetIntData(SqlHandle, 15);
			PMob->m_Link = (uint8)Sql_GetIntData(SqlHandle, 16);
			PMob->m_Type = (uint8)Sql_GetIntData(SqlHandle, 17);
			PMob->m_Immunity = (IMMUNITY)Sql_GetIntData(SqlHandle, 18);
			PMob->m_EcoSystem = (ECOSYSTEM)Sql_GetIntData(SqlHandle, 19);
			PMob->m_ModelSize = (uint8)Sql_GetIntData(SqlHandle, 10);

			PMob->speed = (uint8)Sql_GetIntData(SqlHandle, 21);
			PMob->speedsub = (uint8)Sql_GetIntData(SqlHandle, 21);

			/*if(PMob->speed != 0)
			{
			PMob->speed += map_config.speed_mod;
			// whats this for?
			PMob->speedsub += map_config.speed_mod;
			}*/

			PMob->strRank = (uint8)Sql_GetIntData(SqlHandle, 22);
			PMob->dexRank = (uint8)Sql_GetIntData(SqlHandle, 23);
			PMob->vitRank = (uint8)Sql_GetIntData(SqlHandle, 24);
			PMob->agiRank = (uint8)Sql_GetIntData(SqlHandle, 25);
			PMob->intRank = (uint8)Sql_GetIntData(SqlHandle, 26);
			PMob->mndRank = (uint8)Sql_GetIntData(SqlHandle, 27);
			PMob->chrRank = (uint8)Sql_GetIntData(SqlHandle, 28);
			PMob->evaRank = (uint8)Sql_GetIntData(SqlHandle, 29);
			PMob->defRank = (uint8)Sql_GetIntData(SqlHandle, 30);
			PMob->attRank = (uint8)Sql_GetIntData(SqlHandle, 52);
			PMob->accRank = (uint8)Sql_GetIntData(SqlHandle, 53);

			PMob->setModifier(Mod::SLASHRES, (uint16)(Sql_GetFloatData(SqlHandle, 31) * 1000));
			PMob->setModifier(Mod::PIERCERES, (uint16)(Sql_GetFloatData(SqlHandle, 32) * 1000));
			PMob->setModifier(Mod::HTHRES, (uint16)(Sql_GetFloatData(SqlHandle, 33) * 1000));
			PMob->setModifier(Mod::IMPACTRES, (uint16)(Sql_GetFloatData(SqlHandle, 34) * 1000));

			PMob->setModifier(Mod::FIRERES, (int16)((Sql_GetFloatData(SqlHandle, 35) - 1) * -100)); // These are stored as floating percentages
			PMob->setModifier(Mod::ICERES, (int16)((Sql_GetFloatData(SqlHandle, 36) - 1) * -100)); // and need to be adjusted into modifier units.
			PMob->setModifier(Mod::WINDRES, (int16)((Sql_GetFloatData(SqlHandle, 37) - 1) * -100)); // Higher RES = lower damage.
			PMob->setModifier(Mod::EARTHRES, (int16)((Sql_GetFloatData(SqlHandle, 38) - 1) * -100)); // Negatives signify lower resist chance.
			PMob->setModifier(Mod::THUNDERRES, (int16)((Sql_GetFloatData(SqlHandle, 39) - 1) * -100)); // Positives signify increased resist chance.
			PMob->setModifier(Mod::WATERRES, (int16)((Sql_GetFloatData(SqlHandle, 40) - 1) * -100));
			PMob->setModifier(Mod::LIGHTRES, (int16)((Sql_GetFloatData(SqlHandle, 41) - 1) * -100));
			PMob->setModifier(Mod::DARKRES, (int16)((Sql_GetFloatData(SqlHandle, 42) - 1) * -100));

			PMob->m_Element = (uint8)Sql_GetIntData(SqlHandle, 43);
			PMob->m_Family = (uint16)Sql_GetIntData(SqlHandle, 44);
			PMob->m_name_prefix = (uint8)Sql_GetIntData(SqlHandle, 45);
			PMob->m_flags = (uint32)Sql_GetIntData(SqlHandle, 46);

			//Special sub animation for Mob (yovra, jailer of love, phuabo)
			// yovra 1: en hauteur, 2: en bas, 3: en haut
			// phuabo 1: sous l'eau, 2: sort de l'eau, 3: rentre dans l'eau
			PMob->animationsub = (uint32)Sql_GetIntData(SqlHandle, 47);

			// Setup HP / MP Stat Percentage Boost
			PMob->HPscale = Sql_GetFloatData(SqlHandle, 48);
			PMob->MPscale = Sql_GetFloatData(SqlHandle, 49);

			// Check if we should be looking up scripts for this mob
			PMob->m_HasSpellScript = (uint8)Sql_GetIntData(SqlHandle, 50);

			PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(Sql_GetIntData(SqlHandle, 51));

			PMob->m_Pool = Sql_GetUIntData(SqlHandle, 54);

			PMob->allegiance = Sql_GetUIntData(SqlHandle, 55);
			PMob->namevis = Sql_GetUIntData(SqlHandle, 56);
			PMob->m_Aggro = Sql_GetUIntData(SqlHandle, 57);
			PMob->m_MobSkillList = Sql_GetUIntData(SqlHandle, 58);
			PMob->m_TrueDetection = Sql_GetUIntData(SqlHandle, 59);
			PMob->m_Detects = Sql_GetUIntData(SqlHandle, 60);

			// must be here first to define mobmods
			mobutils::InitializeMob(PMob, zoneutils::GetZone(zoneID));

			zoneutils::GetZone(zoneID)->InsertPET(PMob);

			luautils::OnMobInitialize(PMob);
            luautils::ApplyMixins(PMob);

			PMob->saveModifiers();
			PMob->saveMobModifiers();
		}
	}
	return PMob;
}
Beispiel #17
0
CEntityUpdatePacket::CEntityUpdatePacket(CBaseEntity* PEntity, ENTITYUPDATE type, uint8 updatemask)
{
	this->type = 0x0E;
	this->size = 0x1C;

	WBUFL(data,(0x04)-4) = PEntity->id;
	WBUFW(data,(0x08)-4) = PEntity->targid;
	WBUFB(data,(0x0A)-4) = updatemask;

	switch(type)
	{
		case ENTITY_DESPAWN:
		{
			WBUFB(data,(0x0A)-4) = 0x20;
            updatemask = UPDATE_ALL_MOB;
		}
		break;
		case ENTITY_SPAWN:
		{
            updatemask = UPDATE_ALL_MOB;
			if (PEntity->objtype == TYPE_PET)
			{
				WBUFB(data,(0x28)-4) = 0x04;
			}
			if (PEntity->look.size == MODEL_EQUIPED || PEntity->look.size == MODEL_CHOCOBO)
			{
				updatemask = 0x57;
			}
            WBUFB(data,(0x0A)-4) = updatemask;
		}
		break;
	}

	if (updatemask & UPDATE_POS){
		WBUFB(data,(0x0B)-4) = PEntity->loc.p.rotation;
		WBUFF(data,(0x0C)-4) = PEntity->loc.p.x;
		WBUFF(data,(0x10)-4) = PEntity->loc.p.y;
		WBUFF(data,(0x14)-4) = PEntity->loc.p.z;
		WBUFW(data,(0x18)-4) = PEntity->loc.p.moving;
		WBUFW(data,(0x1A)-4) = PEntity->m_TargID << 1;
		WBUFB(data,(0x1C)-4) = PEntity->speed;
		WBUFB(data,(0x1D)-4) = PEntity->speedsub;
	}

    if (PEntity->allegiance == ALLEGIANCE_PLAYER && PEntity->status == STATUS_UPDATE)
        WBUFB(data, (0x20) - 4) = STATUS_NORMAL;
    else
        WBUFB(data, (0x20) - 4) = PEntity->status;

	switch(PEntity->objtype)
	{
		case TYPE_NPC:
		{
			if (updatemask & UPDATE_HP)
			{
				WBUFB(data,(0x1E)-4) = 0x64;
                WBUFB(data,(0x1F)-4) = PEntity->animation;
                WBUFB(data,(0x2A)-4) = PEntity->animationsub;
				WBUFL(data,(0x21)-4) = ((CNpcEntity*)PEntity)->unknown;
				WBUFB(data,(0x22)-4) |= (PEntity->untargetable ? 0x08 : 0x00);
				WBUFB(data,(0x22)-4) |= (PEntity->hpvis ? 0x00 : 0x01);
				WBUFB(data,(0x27)-4) = ((CNpcEntity*)PEntity)->name_prefix;     // gender and something else
				WBUFB(data,(0x29)-4) = PEntity->allegiance;
				WBUFB(data,(0x2B)-4) = PEntity->namevis;
			}
		}
		break;
		case TYPE_MOB:
		{
			CMobEntity* PMob = (CMobEntity*)PEntity;

			if(PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC && 
				PMob->PBattleAI->GetCurrentAction() == ACTION_FALL)
			{
                WBUFB(data,(0x21)-4) = 0x99;
                //WBUFB (data,(0x27)-4) = 0x28;
                WBUFB(data,(0x1E)-4) = 0x00; //0% HP
                WBUFB(data,(0x1F)-4) = ANIMATION_DEATH; //death anim
                WBUFB(data,(0x20)-4) = STATUS_NORMAL;
				WBUFB(data,(0x29)-4) = PEntity->allegiance;
				WBUFB(data,(0x2B)-4) = PEntity->namevis;
			}
			else
			{
				if (updatemask & UPDATE_HP)
				{
					WBUFB(data,(0x1E)-4) = PMob->GetHPP();
					WBUFB(data,(0x1F)-4) = PEntity->animation;
                    WBUFB(data,(0x2A)-4) = PEntity->animationsub;
					WBUFL(data,(0x21)-4) = PMob->m_unknown;
					WBUFB(data,(0x21)-4) |= PMob->m_CallForHelp;
					WBUFB(data,(0x22)-4) |= (PEntity->untargetable ? 0x08 : 0x00);
					WBUFB(data,(0x22)-4) |= (PEntity->hpvis ? 0x00 : 0x01);
					WBUFB(data,(0x27)-4) = PMob->m_name_prefix;
					if (PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC)
						WBUFB(data,(0x27)-4) |= 0x08;
                    WBUFB(data,(0x28)-4) |= (PMob->StatusEffectContainer->HasStatusEffect(EFFECT_TERROR) ? 0x10 : 0x00);
					WBUFB(data,(0x29)-4) = PEntity->allegiance;
                    WBUFB(data, (0x2B) - 4) = 0;//PEntity->namevis;
				}
				if (updatemask & UPDATE_STATUS)
				{
                    WBUFL(data, (0x2C) - 4) = PMob->m_OwnerID.id;
				}
			}
			if (updatemask & UPDATE_NAME)
			{
				//depending on size of name, this can be 0x20, 0x22, or 0x24
				this->size = 0x24;
				memcpy(data + (0x34) - 4, PEntity->GetName(), (PEntity->name.size() > 15 ? 15 : PEntity->name.size()));
			}
		}
		break;
		case TYPE_PET:
		{
			if(((CPetEntity*)PEntity)->PBattleAI->GetCurrentAction()==ACTION_FALL){
				WBUFB(data,(0x21)-4) = 0x99;
                WBUFB(data,(0x25)-4) = 0x08;
                WBUFB(data,(0x27)-4) = 0x08 | ((CPetEntity*)PEntity)->m_name_prefix;
				WBUFB(data,(0x29)-4) = PEntity->allegiance;
                WBUFB(data,(0x28)-4) = (((CBattleEntity*)PEntity)->health.hp > 0 ? 0x08 : 0x00);
				WBUFB(data,(0x1E)-4) = 0x00; //0% HP
				WBUFB(data,(0x1F)-4) = ANIMATION_DEATH;
				WBUFB(data,(0x20)-4) = STATUS_NORMAL;
			}
			else{
				if (updatemask & UPDATE_HP)
				{
					WBUFB(data,(0x1E)-4) = ((CPetEntity*)PEntity)->GetHPP();
                    WBUFB(data,(0x1F)-4) = PEntity->animation;
                    WBUFB(data,(0x2A)-4) = PEntity->animationsub;
                    WBUFB(data,(0x28)-4) |= (((CPetEntity*)PEntity)->StatusEffectContainer->HasStatusEffect(EFFECT_TERROR) ? 0x10 : 0x00);
                    WBUFB(data,(0x29)-4) = PEntity->allegiance;
				}
				if (updatemask & UPDATE_STATUS)
				{
					WBUFB(data,(0x27)-4) = 0x08 | ((CPetEntity*)PEntity)->m_name_prefix;
				}
				if (updatemask & UPDATE_NAME)
				{
					this->size = 0x24;
					memcpy(data + (0x34) - 4, PEntity->GetName(), (PEntity->name.size() > 15 ? 15 : PEntity->name.size()));
				}
			}
		}
		break;
	}

	switch(PEntity->look.size)
	{
		case MODEL_STANDARD:
		case MODEL_UNK_5:
		case MODEL_AUTOMATON:
		{
			WBUFL(data,(0x30)-4) = RBUFL(&PEntity->look,0);
		}
		break;
		case MODEL_EQUIPED:
        case MODEL_CHOCOBO:
		{
			this->size = 0x24;

			memcpy(data + (0x30) - 4, &(PEntity->look), 20);
		}
		break;
		case MODEL_DOOR:
		case MODEL_ELEVATOR:
		case MODEL_SHIP:
		{
			this->size = 0x24;

			WBUFW (data,(0x30)-4) = PEntity->look.size;
			memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 12 ? 12 : PEntity->name.size()));
		}
		break;
	}
}
Beispiel #18
0
void DespawnPet(CBattleEntity* PMaster)
{
	DSP_DEBUG_BREAK_IF(PMaster->PPet == NULL);

	CBattleEntity* PPet = PMaster->PPet;


	// mob was not reset properly on death/uncharm
	// reset manually
	if (PPet->isCharmed && PMaster->objtype == TYPE_MOB)
	{
		PPet->isCharmed = false;
		PMaster->charmTime = 0;

		delete PPet->PBattleAI;
		PPet->PBattleAI = new CAIMobDummy((CMobEntity*)PMaster);
		PPet->PBattleAI->SetLastActionTime(gettick());
		PPet->PBattleAI->SetCurrentAction(ACTION_FALL);

		ShowDebug("An ex charmed mob was not reset properly, Manually resetting it.\n");
		return;
	}



	switch (PPet->objtype)
	{
		case TYPE_PET:
		{
			PPet->PBattleAI->SetCurrentAction(ACTION_FALL);
			if( ((CPetEntity*)PPet)->getPetType() == PETTYPE_AVATAR )
				PMaster->setModifier(MOD_AVATAR_PERPETUATION, 0);

			if (PMaster->PParty != NULL)
			{
				for (uint8 i = 0; i < PMaster->PParty->members.size(); ++i)
				{
					CCharEntity* PMember = (CCharEntity*)PMaster->PParty->members.at(i);
					PMember->PLatentEffectContainer->CheckLatentsPartyAvatar();
				}
			}
				CCharEntity* PChar = (CCharEntity*)PMaster;
				PChar->PLatentEffectContainer->CheckLatentsPartyAvatar();
		}
		break;
		case TYPE_MOB:
		{
				if(PMaster->objtype == TYPE_PC)
				{

					CMobEntity* PMob = (CMobEntity*)PMaster->PPet;
					CCharEntity* PChar = (CCharEntity*)PMaster;


					// mobs charm wears off whist fighting another mob. Both mobs now attack player since mobs are no longer enemies
					if(PMob->PBattleAI != NULL && PMob->PBattleAI->GetBattleTarget() != NULL && PMob->PBattleAI->GetBattleTarget()->objtype == TYPE_MOB){
						((CMobEntity*)PMob->PBattleAI->GetBattleTarget())->PEnmityContainer->Clear();
						((CMobEntity*)PMob->PBattleAI->GetBattleTarget())->PEnmityContainer->UpdateEnmity(PChar, 0, 0);
					}

					//clear the ex-charmed mobs enmity
					PMob->PEnmityContainer->Clear();

					// charm time is up, mob attacks player now
					if (PMob->GetHPP() != 0 && PMob->PMaster->GetHPP() != 0 && distance(PMob->loc.p, PMob->PMaster->loc.p) < 30)
					{
						PMob->PEnmityContainer->UpdateEnmity(PChar, 0, 0);
					}
					else
					{
						PMob->m_OwnerID.clean();
					}

					// dirty exp if not full
					PMob->m_giveExp = PMob->GetHPP() == 100;

					//master using leave command
					if (PMaster->PBattleAI->GetCurrentAction() == ACTION_JOBABILITY_FINISH && PMaster->PBattleAI->GetCurrentJobAbility()->getID() == 55 || PChar->loc.zoning)
					{
						PMob->PEnmityContainer->Clear();
						PMob->m_OwnerID.clean();
					}

					PMob->isCharmed = false;
					PMob->charmTime = 0;
					PMob->PMaster = NULL;

					delete PMob->PBattleAI;
					PMob->PBattleAI = new CAIMobDummy(PMob);

					PMob->PBattleAI->SetLastActionTime(gettick());

					if (PMob->GetHPP() == 0)
						PMob->PBattleAI->SetCurrentAction(ACTION_FALL);
					else
						PMob->PBattleAI->SetCurrentAction(ACTION_DISENGAGE);


					PChar->PPet = NULL;
					PChar->pushPacket(new CCharUpdatePacket(PChar));
					PMob->loc.zone->PushPacket(PMob, CHAR_INRANGE, new CEntityUpdatePacket(PMob, ENTITY_UPDATE));
				}

		}
		break;
		case TYPE_PC:
		{
			// освобождаем персонажа из под контроля
		}
		break;
	}
}
CEntityUpdatePacket::CEntityUpdatePacket(CBaseEntity* PEntity, ENTITYUPDATE type, uint8 updatemask)
{
    this->type = 0x0E;
    this->size = 0x1C;

    ref<uint32>(0x04) = PEntity->id;
    ref<uint16>(0x08) = PEntity->targid;
    ref<uint8>(0x0A) = updatemask;

    switch (type)
    {
        case ENTITY_DESPAWN:
        {
            ref<uint8>(0x0A) = 0x20;
            updatemask = UPDATE_ALL_MOB;
        }
        break;
        case ENTITY_SPAWN:
        {
            updatemask = UPDATE_ALL_MOB;
            if (PEntity->objtype == TYPE_PET)
            {
                ref<uint8>(0x28) = 0x04;
            }
            if (PEntity->look.size == MODEL_EQUIPED || PEntity->look.size == MODEL_CHOCOBO)
            {
                updatemask = 0x57;
            }
            ref<uint8>(0x0A) = updatemask;
        }
        break;
        default:
        {
            break;
        }
    }

    if (updatemask & UPDATE_POS) {
        ref<uint8>(0x0B) = PEntity->loc.p.rotation;
        ref<float>(0x0C) = PEntity->loc.p.x;
        ref<float>(0x10) = PEntity->loc.p.y;
        ref<float>(0x14) = PEntity->loc.p.z;
        ref<uint16>(0x18) = PEntity->loc.p.moving;
        ref<uint16>(0x1A) = PEntity->m_TargID << 1;
        ref<uint8>(0x1C) = PEntity->speed;
        ref<uint8>(0x1D) = PEntity->speedsub;
    }

    if (PEntity->allegiance == ALLEGIANCE_PLAYER && PEntity->status == STATUS_MOB)
        ref<uint8>(0x20) = STATUS_NORMAL;
    else
        ref<uint8>(0x20) = PEntity->status;

    switch (PEntity->objtype)
    {
        case TYPE_NPC:
        {
            if (updatemask & UPDATE_HP)
            {
                ref<uint8>(0x1E) = 0x64;
                ref<uint8>(0x1F) = PEntity->animation;
                ref<uint8>(0x2A) = PEntity->animationsub;
                ref<uint32>(0x21) = ((CNpcEntity*)PEntity)->m_flags;
                ref<uint8>(0x27) = ((CNpcEntity*)PEntity)->name_prefix;     // gender and something else
                ref<uint8>(0x29) = PEntity->allegiance;
                ref<uint8>(0x2B) = PEntity->namevis;
            }
        }
        break;
        case TYPE_MOB:
        case TYPE_PET:
        {
            CMobEntity* PMob = (CMobEntity*)PEntity;

            //if(PMob->PMaster != nullptr && PMob->PMaster->objtype == TYPE_PC && 
            //	PMob->PBattleAI->GetCurrentAction() == ACTION_FALL)
            //{
            //    ref<uint8>(data,(0x21)) = 0x99;
            //    //ref<uint8> (data,(0x27)) = 0x28;
            //    ref<uint8>(data,(0x1E)) = 0x00; //0% HP
            //    ref<uint8>(data,(0x1F)) = ANIMATION_DEATH; //death anim
            //    ref<uint8>(data,(0x20)) = STATUS_NORMAL;
            //	  ref<uint8>(data,(0x29)) = PEntity->allegiance;
            //	  ref<uint8>(data,(0x2B)) = PEntity->namevis;
            //}
            //else
            {
                if (updatemask & UPDATE_HP)
                {
                    ref<uint8>(0x1E) = PMob->GetHPP();
                    ref<uint8>(0x1F) = PEntity->animation;
                    ref<uint8>(0x2A) = PEntity->animationsub;
                    ref<uint32>(0x21) = PMob->m_flags;
                    ref<uint8>(0x25) = PMob->health.hp > 0 ? 0x08 : 0;
                    ref<uint8>(0x27) = PMob->m_name_prefix;
                    if (PMob->PMaster != nullptr && PMob->PMaster->objtype == TYPE_PC)
                        ref<uint8>(0x27) |= 0x08;
                    ref<uint8>(0x28) |= (PMob->StatusEffectContainer->HasStatusEffect(EFFECT_TERROR) ? 0x10 : 0x00);
                    ref<uint8>(0x28) |= PMob->health.hp > 0 && PMob->animation == ANIMATION_DEATH ? 0x08 : 0;
                    ref<uint8>(0x29) = PEntity->allegiance;
                    ref<uint8>(0x2B) = PEntity->namevis;
                }
                if (updatemask & UPDATE_STATUS)
                {
                    ref<uint32>(0x2C) = PMob->m_OwnerID.id;
                }
            }
            if (updatemask & UPDATE_NAME)
            {
                //depending on size of name, this can be 0x20, 0x22, or 0x24
                this->size = 0x24;
                if (PMob->packetName.empty())
                    memcpy(data + (0x34), PEntity->GetName(), (PEntity->name.size() > 15 ? 15 : PEntity->name.size()));
                else
                    memcpy(data + (0x34), PMob->packetName.c_str(), (PMob->packetName.size() > 15 ? 15 : PMob->packetName.size()));
            }
        }
        break;
        default:
        {
            break;
        }
    }

    switch (PEntity->look.size)
    {
        case MODEL_STANDARD:
        case MODEL_UNK_5:
        case MODEL_AUTOMATON:
        {
            ref<uint32>(0x30) = ::ref<uint32>(&PEntity->look, 0);
        }
        break;
        case MODEL_EQUIPED:
        case MODEL_CHOCOBO:
        {
            this->size = 0x24;

            memcpy(data + (0x30), &(PEntity->look), 20);
        }
        break;
        case MODEL_DOOR:
        case MODEL_ELEVATOR:
        case MODEL_SHIP:
        {
            this->size = 0x24;

            ref<uint16>(0x30) = PEntity->look.size;
            memcpy(data + (0x34), PEntity->GetName(), (PEntity->name.size() > 12 ? 12 : PEntity->name.size()));
        }
        break;
    }
}
Beispiel #20
0
	/***************************************************************
		Spawns monsters for the given BCNMID/Instance number by
		looking at bcnm_instance table for mob ids then spawning
		them and adding them to the monster list for the given
		instance.
	****************************************************************/
	bool spawnMonstersForBcnm(CInstance* instance){
		DSP_DEBUG_BREAK_IF(instance==NULL);

		//get ids from DB
		const int8* fmtQuery = "SELECT monsterId, conditions \
						    FROM bcnm_instance \
							WHERE bcnmId = %u AND instanceNumber = %u";

		int32 ret = Sql_Query(SqlHandle, fmtQuery, instance->getID(), instance->getInstanceNumber());

		if (ret == SQL_ERROR ||
			Sql_NumRows(SqlHandle) == 0)
		{
			ShowError("spawnMonstersForBcnm : SQL error - Cannot find any monster IDs for BCNMID %i Instance %i \n",
				instance->getID(), instance->getInstanceNumber());
		}
		else{
			while(Sql_NextRow(SqlHandle) == SQL_SUCCESS){
				uint32 mobid = Sql_GetUIntData(SqlHandle,0);
				uint8 condition = Sql_GetUIntData(SqlHandle,1);
				CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB);
				if (PMob != NULL)
				{

					PMob->m_instanceID = instance->getInstanceNumber();
					PMob->m_bcnmID = instance->getID();

					if (condition & CONDITION_SPAWNED_AT_START)
					{
						// This condition is needed for some mob at dynamis, else he don't pop
						if(PMob->PBattleAI->GetCurrentAction() == ACTION_FADE_OUT){
							PMob->PBattleAI->SetLastActionTime(0);
							PMob->PBattleAI->SetCurrentAction(ACTION_NONE);
						}
						if (PMob->PBattleAI->GetCurrentAction() == ACTION_NONE ||
							PMob->PBattleAI->GetCurrentAction() == ACTION_SPAWN)
						{
							PMob->PBattleAI->SetLastActionTime(0);
							PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);

							if(strcmp(PMob->GetName(),"Maat")==0){
								mobutils::SetupMaat(PMob, (JOBTYPE)instance->getPlayerMainJob());
								PMob->m_DropID = 4485; //Give Maat his stealable Warp Scroll 

								// disable players subjob
								instance->disableSubJob();

								// disallow subjob, this will enable for later
								instance->m_RuleMask &= ~(1 << RULES_ALLOW_SUBJOBS);

							}
							//ShowDebug("Spawned %s (%u) id %i inst %i \n",PMob->GetName(),PMob->id,instance->getID(),instance->getInstanceNumber());
							instance->addEnemy(PMob, condition);
						} else {
							ShowDebug(CL_CYAN"SpawnMobForBcnm: <%s> (%u) is alredy spawned\n" CL_RESET, PMob->GetName(), PMob->id);
						}
					} else {
						instance->addEnemy(PMob, condition);
					}
				} else {
				    ShowDebug("SpawnMobForBcnm: mob %u not found\n", mobid);
				}
			}
			return true;
		}
		return false;
	}
Beispiel #21
0
void CAIPetDummy::ActionAbilityStart()
{
    if (m_PPet->StatusEffectContainer->HasPreventActionEffect())
    {
        return;
    }

    if (m_PPet->objtype == TYPE_MOB && m_PPet->PMaster->objtype == TYPE_PC)
    {
        if (m_MasterCommand == MASTERCOMMAND_SIC && m_PPet->health.tp >= 1000 && m_PBattleTarget != nullptr)
        {
            m_MasterCommand = MASTERCOMMAND_NONE;
            CMobEntity* PMob = (CMobEntity*)m_PPet->PMaster->PPet;
            std::vector<uint16> MobSkills = battleutils::GetMobSkillList(PMob->getMobMod(MOBMOD_SKILL_LIST));

            if (MobSkills.size() > 0)
            {
                std::shuffle(MobSkills.begin(), MobSkills.end(), dsprand::mt());

                for (auto&& skillid : MobSkills)
                {
                    auto PMobSkill = battleutils::GetMobSkill(skillid);
                    if (PMobSkill && luautils::OnMobSkillCheck(m_PBattleTarget, m_PPet, PMobSkill) == 0)
                    {
                        SetCurrentMobSkill(PMobSkill);
                        break;
                    }
                }

                // could not find skill
                if (!GetCurrentMobSkill())
                {
                    TransitionBack(true);
                    return;
                }

                preparePetAbility(m_PBattleTarget);
                return;
            }
            return;
        }
    }


    if (m_PPet->getPetType() == PETTYPE_JUG_PET) {
        if (m_MasterCommand == MASTERCOMMAND_SIC && m_PPet->health.tp >= 1000 && m_PBattleTarget != nullptr) { //choose random tp move
            m_MasterCommand = MASTERCOMMAND_NONE;
            if (m_PPet->PetSkills.size() > 0) {
                auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(dsprand::GetRandomNumber(m_PPet->PetSkills.size())));
                if (PMobSkill)
                {
                    SetCurrentMobSkill(PMobSkill);
                    preparePetAbility(m_PBattleTarget);
                    return;
                }
            }
        }
    }
    else if (m_PPet->getPetType() == PETTYPE_AVATAR) {
        for (int i = 0; i < m_PPet->PetSkills.size(); i++) {
            auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(i));
            if (PMobSkill && PMobSkill->getAnimationTime() == m_MasterCommand) {
                SetCurrentMobSkill(PMobSkill);
                m_MasterCommand = MASTERCOMMAND_NONE;
                preparePetAbility(m_PPet);
                return;
            }
        }
        m_MasterCommand = MASTERCOMMAND_NONE;
    }
    else if (m_PPet->getPetType() == PETTYPE_WYVERN) {

        WYVERNTYPE wyverntype = m_PPet->getWyvernType();

        if (m_MasterCommand == MASTERCOMMAND_ELEMENTAL_BREATH && (wyverntype == WYVERNTYPE_MULTIPURPOSE || wyverntype == WYVERNTYPE_OFFENSIVE)) {
            m_MasterCommand = MASTERCOMMAND_NONE;

            //offensive or multipurpose wyvern
            if (m_PBattleTarget != nullptr) { //prepare elemental breaths
                int skip = dsprand::GetRandomNumber(6);
                int hasSkipped = 0;

                for (int i = 0; i < m_PPet->PetSkills.size(); i++) {
                    auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(i));
                    if (PMobSkill && PMobSkill->getValidTargets() == TARGET_ENEMY) {
                        if (hasSkipped == skip) {
                            SetCurrentMobSkill(PMobSkill);
                            break;
                        }
                        else {
                            hasSkipped++;
                        }
                    }
                }

                preparePetAbility(m_PBattleTarget);
                return;
            }

        }
        else if (m_MasterCommand == MASTERCOMMAND_HEALING_BREATH && (wyverntype == WYVERNTYPE_DEFENSIVE || wyverntype == WYVERNTYPE_MULTIPURPOSE))
        {

            m_MasterCommand = MASTERCOMMAND_NONE;
            m_PBattleSubTarget = nullptr;
            //TODO: CHECK FOR STATUS EFFECTS FOR REMOVE- BREATH (higher priority than healing breaths)

            //	if(m_PPet->PMaster->PParty==nullptr){//solo with master-kun
            CItemArmor* masterHeadItem = ((CCharEntity*)(m_PPet->PMaster))->getEquip(SLOT_HEAD);

            uint16 masterHead = masterHeadItem ? masterHeadItem->getID() : 0;

            // Determine what the required HP percentage will need to be 
            // at or under in order for healing breath to activate.
            uint8 requiredHPP = 0;
            if (((CCharEntity*)(m_PPet->PMaster))->objtype == TYPE_PC && (masterHead == 12519 || masterHead == 15238)) { //Check for player & AF head, or +1
                if (wyverntype == WYVERNTYPE_DEFENSIVE) { //healer wyvern
                    requiredHPP = 50;
                }
                else if (wyverntype == WYVERNTYPE_MULTIPURPOSE) { //hybrid wyvern
                    requiredHPP = 33;
                }
            }
            else {
                if (wyverntype == WYVERNTYPE_DEFENSIVE) { //healer wyvern
                    requiredHPP = 33;
                }
                else if (wyverntype == WYVERNTYPE_MULTIPURPOSE) { //hybrid wyvern
                    requiredHPP = 25;
                }
            }

            // Only attempt to find a target if there is an HP percentage to calculate.
            if (requiredHPP) {
                CBattleEntity* master = m_PPet->PMaster;
                // Check the master first.
                if (master->GetHPP() <= requiredHPP) {
                    m_PBattleSubTarget = master;
                }

                // Otherwise if this is a healer wyvern, and the member is in a party 
                // check all of the party members who qualify.
                else if (wyverntype == WYVERNTYPE_DEFENSIVE && master->PParty != nullptr) {
                    master->ForParty([this, requiredHPP](CBattleEntity* PTarget) {
                        if (PTarget->GetHPP() <= requiredHPP) {
                            m_PBattleSubTarget = PTarget;
                        }
                    });
                }
            }

            if (m_PBattleSubTarget != nullptr) { //target to heal
                //get highest breath for wyverns level
                m_PMobSkill = nullptr;
                for (int i = 0; i < m_PPet->PetSkills.size(); i++) {
                    auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(i));
                    if (PMobSkill && PMobSkill->getValidTargets() == TARGET_PLAYER_PARTY) {
                        if (PMobSkill->getID() == 638 &&
                            m_PPet->PMaster->GetMLevel() < 20) { //can only using hb1
                            SetCurrentMobSkill(PMobSkill);
                            break;
                        }
                        else if (PMobSkill->getID() == 639 &&
                            m_PPet->PMaster->GetMLevel() < 40) { //can only using hb2
                            SetCurrentMobSkill(PMobSkill);
                            break;
                        }
                        else if (PMobSkill->getID() == 640 &&
                            m_PPet->PMaster->GetMLevel() >= 40) { //can only using hb3
                            SetCurrentMobSkill(PMobSkill);
                            break;
                        }
                    }
                }
                preparePetAbility(m_PBattleSubTarget);
                return;
            }
        }
    }

    TransitionBack(true);
}
Beispiel #22
0
void LoadMOBList()
{
    const int8* Query =
        "SELECT zoneid, name, mobid, pos_rot, pos_x, pos_y, pos_z, \
			respawntime, spawntype, dropid, mob_groups.HP, mob_groups.MP, minLevel, maxLevel, \
			modelid, mJob, sJob, cmbSkill, cmbDmgMult, cmbDelay, behavior, links, mobType, immunity, \
			systemid, mobsize, speed, \
			STR, DEX, VIT, AGI, `INT`, MND, CHR, EVA, DEF, \
			Slash, Pierce, H2H, Impact, \
			Fire, Ice, Wind, Earth, Lightning, Water, Light, Dark, Element, \
			mob_pools.familyid, name_prefix, unknown, animationsub, \
			(mob_family_system.HP / 100), (mob_family_system.MP / 100), hasSpellScript, spellList, ATT, ACC, mob_groups.poolid \
			FROM mob_groups INNER JOIN mob_pools ON mob_groups.poolid = mob_pools.poolid \
			INNER JOIN mob_spawn_points ON mob_groups.groupid = mob_spawn_points.groupid \
			INNER JOIN mob_family_system ON mob_pools.familyid = mob_family_system.familyid \
			WHERE NOT (pos_x = 0 AND pos_y = 0 AND pos_z = 0);";

    int32 ret = Sql_Query(SqlHandle, Query);

	if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0)
	{
		while(Sql_NextRow(SqlHandle) == SQL_SUCCESS)
		{
        	uint16 ZoneID = (uint16)Sql_GetUIntData(SqlHandle, 0);
			CMobEntity* PMob = new CMobEntity;

			PMob->name.insert(0,Sql_GetData(SqlHandle,1));
			PMob->id = (uint32)Sql_GetUIntData(SqlHandle,2);
			PMob->targid = (uint16)PMob->id & 0x0FFF;

			PMob->m_SpawnPoint.rotation = (uint8)Sql_GetIntData(SqlHandle,3);
			PMob->m_SpawnPoint.x = Sql_GetFloatData(SqlHandle,4);
			PMob->m_SpawnPoint.y = Sql_GetFloatData(SqlHandle,5);
			PMob->m_SpawnPoint.z = Sql_GetFloatData(SqlHandle,6);

			PMob->m_RespawnTime = Sql_GetUIntData(SqlHandle,7) * 1000;
			PMob->m_SpawnType   = (SPAWNTYPE)Sql_GetUIntData(SqlHandle,8);
			PMob->m_DropID		= Sql_GetUIntData(SqlHandle,9);

			PMob->HPmodifier = (uint32)Sql_GetIntData(SqlHandle,10);
			PMob->MPmodifier = (uint32)Sql_GetIntData(SqlHandle,11);

			PMob->m_minLevel = (uint8)Sql_GetIntData(SqlHandle,12);
			PMob->m_maxLevel = (uint8)Sql_GetIntData(SqlHandle,13);

			memcpy(&PMob->look,Sql_GetData(SqlHandle,14),23);

			PMob->SetMJob(Sql_GetIntData(SqlHandle,15));
			PMob->SetSJob(Sql_GetIntData(SqlHandle,16));

			PMob->m_Weapons[SLOT_MAIN]->setMaxHit(1);
			PMob->m_Weapons[SLOT_MAIN]->setSkillType(Sql_GetIntData(SqlHandle,17));
			PMob->m_dmgMult = Sql_GetUIntData(SqlHandle, 18);
			PMob->m_Weapons[SLOT_MAIN]->setDelay((Sql_GetIntData(SqlHandle,19) * 1000)/60);
			PMob->m_Weapons[SLOT_MAIN]->setBaseDelay((Sql_GetIntData(SqlHandle,19) * 1000)/60);

			PMob->m_Behaviour  = (uint16)Sql_GetIntData(SqlHandle,20);
			PMob->m_Link       = (uint8)Sql_GetIntData(SqlHandle,21);
			PMob->m_Type       = (uint8)Sql_GetIntData(SqlHandle,22);
			PMob->m_Immunity   = (IMMUNITY)Sql_GetIntData(SqlHandle,23);
			PMob->m_EcoSystem  = (ECOSYSTEM)Sql_GetIntData(SqlHandle,24);
			PMob->m_ModelSize += (uint8)Sql_GetIntData(SqlHandle,25);

			PMob->speed    = (uint8)Sql_GetIntData(SqlHandle,26);
			PMob->speedsub = (uint8)Sql_GetIntData(SqlHandle,26);

			/*if(PMob->speed != 0)
			{
				PMob->speed += map_config.speed_mod;
                // whats this for?
				PMob->speedsub += map_config.speed_mod;
			}*/

            PMob->strRank = (uint8)Sql_GetIntData(SqlHandle,27);
            PMob->dexRank = (uint8)Sql_GetIntData(SqlHandle,28);
            PMob->vitRank = (uint8)Sql_GetIntData(SqlHandle,29);
            PMob->agiRank = (uint8)Sql_GetIntData(SqlHandle,30);
            PMob->intRank = (uint8)Sql_GetIntData(SqlHandle,31);
            PMob->mndRank = (uint8)Sql_GetIntData(SqlHandle,32);
            PMob->chrRank = (uint8)Sql_GetIntData(SqlHandle,33);
            PMob->evaRank = (uint8)Sql_GetIntData(SqlHandle,34);
            PMob->defRank = (uint8)Sql_GetIntData(SqlHandle,35);
            PMob->attRank = (uint8)Sql_GetIntData(SqlHandle,57);
            PMob->accRank = (uint8)Sql_GetIntData(SqlHandle,58);

			PMob->setModifier(MOD_SLASHRES, (uint16)(Sql_GetFloatData(SqlHandle,36) * 1000));
			PMob->setModifier(MOD_PIERCERES,(uint16)(Sql_GetFloatData(SqlHandle,37) * 1000));
			PMob->setModifier(MOD_HTHRES,   (uint16)(Sql_GetFloatData(SqlHandle,38) * 1000));
			PMob->setModifier(MOD_IMPACTRES,(uint16)(Sql_GetFloatData(SqlHandle,39) * 1000));

            PMob->setModifier(MOD_FIREDEF,    (int16)((Sql_GetFloatData(SqlHandle, 40) - 1) * -1000)); // These are stored as floating percentages
            PMob->setModifier(MOD_ICEDEF,     (int16)((Sql_GetFloatData(SqlHandle, 41) - 1) * -1000)); // and need to be adjusted into modifier units.
            PMob->setModifier(MOD_WINDDEF,    (int16)((Sql_GetFloatData(SqlHandle, 42) - 1) * -1000)); // Higher DEF = lower damage.
            PMob->setModifier(MOD_EARTHDEF,   (int16)((Sql_GetFloatData(SqlHandle, 43) - 1) * -1000)); // Negatives signify increased damage.
            PMob->setModifier(MOD_THUNDERDEF, (int16)((Sql_GetFloatData(SqlHandle, 44) - 1) * -1000)); // Positives signify reduced damage.
            PMob->setModifier(MOD_WATERDEF,   (int16)((Sql_GetFloatData(SqlHandle, 45) - 1) * -1000)); // Ex: 125% damage would be 1.25, 50% damage would be 0.50
            PMob->setModifier(MOD_LIGHTDEF,   (int16)((Sql_GetFloatData(SqlHandle, 46) - 1) * -1000)); // (1.25 - 1) * -1000 = -250 DEF
            PMob->setModifier(MOD_DARKDEF,    (int16)((Sql_GetFloatData(SqlHandle, 47) - 1) * -1000)); // (0.50 - 1) * -1000 = 500 DEF

            PMob->setModifier(MOD_FIRERES,    (int16)((Sql_GetFloatData(SqlHandle, 40) - 1) * -100)); // These are stored as floating percentages
            PMob->setModifier(MOD_ICERES,     (int16)((Sql_GetFloatData(SqlHandle, 41) - 1) * -100)); // and need to be adjusted into modifier units.
            PMob->setModifier(MOD_WINDRES,    (int16)((Sql_GetFloatData(SqlHandle, 42) - 1) * -100)); // Higher RES = lower damage.
            PMob->setModifier(MOD_EARTHRES,   (int16)((Sql_GetFloatData(SqlHandle, 43) - 1) * -100)); // Negatives signify lower resist chance.
            PMob->setModifier(MOD_THUNDERRES, (int16)((Sql_GetFloatData(SqlHandle, 44) - 1) * -100)); // Positives signify increased resist chance.
            PMob->setModifier(MOD_WATERRES,   (int16)((Sql_GetFloatData(SqlHandle, 45) - 1) * -100));
            PMob->setModifier(MOD_LIGHTRES,   (int16)((Sql_GetFloatData(SqlHandle, 46) - 1) * -100));
            PMob->setModifier(MOD_DARKRES,    (int16)((Sql_GetFloatData(SqlHandle, 47) - 1) * -100));

			PMob->m_Element = (uint8)Sql_GetIntData(SqlHandle,48);
			PMob->m_Family = (uint16)Sql_GetIntData(SqlHandle,49);
			PMob->m_name_prefix = (uint8)Sql_GetIntData(SqlHandle,50);
			PMob->m_unknown = (uint32)Sql_GetIntData(SqlHandle,51);

			//Special sub animation for Mob (yovra, jailer of love, phuabo)
			// yovra 1: en hauteur, 2: en bas, 3: en haut
			// phuabo 1: sous l'eau, 2: sort de l'eau, 3: rentre dans l'eau
			PMob->animationsub = (uint32)Sql_GetIntData(SqlHandle,52);

			// Setup HP / MP Stat Percentage Boost
			PMob->HPscale = Sql_GetFloatData(SqlHandle,53);
			PMob->MPscale = Sql_GetFloatData(SqlHandle,54);

			PMob->PBattleAI = new CAIMobDummy(PMob);

			if (PMob->m_AllowRespawn = PMob->m_SpawnType == SPAWNTYPE_NORMAL)
			{
				PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);
			}

			// Check if we should be looking up scripts for this mob
			PMob->m_HasSpellScript = (uint8)Sql_GetIntData(SqlHandle,55);

			PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(Sql_GetIntData(SqlHandle,56));

			PMob->m_Pool = Sql_GetUIntData(SqlHandle,59);

            // must be here first to define mobmods
			mobutils::InitializeMob(PMob, GetZone(ZoneID));

            GetZone(ZoneID)->InsertMOB(PMob);

            luautils::OnMobInitialize(PMob);

            PMob->saveModifiers();
            PMob->saveMobModifiers();
		}
	}

	// attach pets to mobs
	const int8* PetQuery =
		"SELECT zoneid, mob_mobid, pet_offset \
		FROM mob_pets \
		LEFT JOIN mob_spawn_points ON mob_pets.mob_mobid = mob_spawn_points.mobid \
		LEFT JOIN mob_groups ON mob_spawn_points.groupid = mob_groups.groupid;";

	ret = Sql_Query(SqlHandle, PetQuery);

	if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0)
	{
		while(Sql_NextRow(SqlHandle) == SQL_SUCCESS)
		{
        	uint16 ZoneID = (uint16)Sql_GetUIntData(SqlHandle, 0);
			uint32 masterid = (uint32)Sql_GetUIntData(SqlHandle,1);
			uint32 petid = masterid + (uint32)Sql_GetUIntData(SqlHandle,2);

			CMobEntity* PMaster = (CMobEntity*)GetZone(ZoneID)->GetEntity(masterid & 0x0FFF, TYPE_MOB);
			CMobEntity* PPet = (CMobEntity*)GetZone(ZoneID)->GetEntity(petid & 0x0FFF, TYPE_MOB);

			if(PMaster == NULL)
			{
				ShowError("zoneutils::loadMOBList PMaster is null. masterid: %d. Make sure x,y,z are not zeros, and that all entities are entered in the database!\n", masterid);
			}
			else if(PPet == NULL)
			{
				ShowError("zoneutils::loadMOBList PPet is null. petid: %d. Make sure x,y,z are not zeros!\n", petid);
			}
			else if(masterid == petid)
			{
				ShowError("zoneutils::loadMOBList Master and Pet are the same entity: %d\n", masterid);
			}
			else
			{
				// pet is always spawned by master
				PPet->m_AllowRespawn = false;
				PPet->m_SpawnType = SPAWNTYPE_SCRIPTED;
				PPet->PBattleAI->SetCurrentAction(ACTION_NONE);
				PPet->SetDespawnTimer(0);

				PMaster->PPet = PPet;
				PPet->PMaster = PMaster;
			}
		}
	}
}
CEntityUpdatePacket::CEntityUpdatePacket(CBaseEntity* PEntity, ENTITYUPDATE type)
{
	this->type = 0x0E;
	this->size = 0x1C;

	WBUFL(data,(0x04)-4) = PEntity->id;
	WBUFW(data,(0x08)-4) = PEntity->targid;

	switch(type)
	{
		case ENTITY_DESPAWN:
		{
			switch(PEntity->objtype)
			{
				case TYPE_NPC:
				{
					WBUFB(data,(0x0A)-4) = 0x20;
				}
				break;
				case TYPE_MOB:
				{
					WBUFB(data,(0x0A)-4) = 0x07;
					WBUFB(data,(0x20)-4) = 0x07;
				}
				break;
				case TYPE_PET:
				{
					WBUFB(data,(0x0A)-4) = 0x20;
				}
				break;
			}
		}
		break;
		case ENTITY_SPAWN:
		{
			switch(PEntity->objtype)
			{
				case TYPE_PET:
				{
					WBUFB(data,(0x28)-4) = 0x04;
				}
				break;
			}
		}
		case ENTITY_UPDATE:
		{
			WBUFB(data,(0x0B)-4) = PEntity->loc.p.rotation;
			WBUFF(data,(0x0C)-4) = PEntity->loc.p.x;
			WBUFF(data,(0x10)-4) = PEntity->loc.p.y;
			WBUFF(data,(0x14)-4) = PEntity->loc.p.z;
			WBUFW(data,(0x18)-4) = PEntity->loc.p.moving;
			WBUFW(data,(0x1A)-4) = PEntity->m_TargID << 1;
			WBUFB(data,(0x1C)-4) = PEntity->speed;
			WBUFB(data,(0x1D)-4) = PEntity->speedsub;
			WBUFB(data,(0x1F)-4) = PEntity->animation;

			WBUFB(data,(0x20)-4) = PEntity->status;
			WBUFB(data,(0x2A)-4) = PEntity->animationsub;

			WBUFB(data,(0x2B)-4) = PEntity->namevis;

			switch(PEntity->objtype)
			{
				case TYPE_NPC:
				{
					WBUFB(data,(0x1E)-4) = 0x64;
					WBUFL(data,(0x21)-4) = ((CNpcEntity*)PEntity)->unknown;
                    WBUFB(data,(0x27)-4) = ((CNpcEntity*)PEntity)->name_prefix;     // gender and something else
				}
				break;
				case TYPE_MOB:
				{
					CMobEntity* PMob = (CMobEntity*)PEntity;

					if(PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC)
					{
						//charmed mob
						if(PMob->PMaster->objtype = TYPE_PC)
						{
							if(PMob->PBattleAI->GetCurrentAction()==ACTION_FALL)
							{
									WBUFB(data,(0x0A)-4) = 0x07;
									WBUFB (data,(0x21)-4) = 0x99;
									//WBUFB (data,(0x27)-4) = 0x28;
									WBUFW(data,(0x1A)-4) = 0x00;
									WBUFW(data,(0x1B)-4) = 0x00;
									WBUFB (data,(0x1E)-4) = 0x00; //0% HP
									WBUFB (data,(0x1F)-4) = ANIMATION_DEATH; //death anim
									WBUFB (data,(0x20)-4) = STATUS_NORMAL;
							}
							else
							{
									this->size = 0x24;
									WBUFB (data,(0x1E)-4) = PMob->GetHPP();
									WBUFB (data,(0x27)-4) = 0x08;
									memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 15 ? 15 : PEntity->name.size()));
							}
						}
					}
					else
					{

						WBUFB(data,(0x1E)-4) = PMob->GetHPP();
						WBUFL(data,(0x21)-4) = PMob->m_unknown;
						WBUFB(data,(0x21)-4) |= PMob->m_CallForHelp;
						WBUFB(data,(0x27)-4) = PMob->m_name_prefix;
						WBUFL(data,(0x2C)-4) = PMob->m_OwnerID.id;
						//set bit0 to 1 to make HP bars invisible e.g. Yilgeban, another bit somewhere controls mob targetability
						//WBUFB(data,(0x22)-4) = 0;

						if (PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC)
							WBUFB(data,(0x27)-4) = 0x08; //todo: may need |=
					}
				}
				break;
				case TYPE_PET:
				{
					if(((CPetEntity*)PEntity)->PBattleAI->GetCurrentAction()==ACTION_FALL){
						WBUFB(data,(0x0A)-4) = 0x07;
						WBUFB(data,(0x21)-4) = 0x99;
					  //WBUFB(data,(0x27)-4) = 0x28;
						WBUFW(data,(0x1A)-4) = 0x00;
						WBUFB(data,(0x1E)-4) = 0x00; //0% HP
						WBUFB(data,(0x1F)-4) = ANIMATION_DEATH;
						WBUFB(data,(0x20)-4) = STATUS_NORMAL;
					}
					else{
						this->size = 0x24;
						WBUFB (data,(0x1E)-4) = ((CPetEntity*)PEntity)->GetHPP();
						WBUFB (data,(0x27)-4) = 0x08;
						memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 15 ? 15 : PEntity->name.size()));
					}
				}
				break;
			}

			switch(PEntity->look.size)
			{
				case MODEL_STANDARD:
				case MODEL_UNK_5:
				case MODEL_UNK_6:
				{
					WBUFB(data,(0x0A)-4) = 0x0F;
					WBUFL(data,(0x30)-4) = RBUFL(&PEntity->look,0);
				}
				break;
				case MODEL_EQUIPED:
                case MODEL_CHOCOBO:
				{
					this->size = 0x24;

					WBUFB (data,(0x0A)-4) = 0x57;
					memcpy(data+(0x30)-4, &(PEntity->look), 20);
				}
				break;
				case MODEL_DOOR:
				case MODEL_ELEVATOR:
				case MODEL_SHIP:
				{
					this->size = 0x24;

					WBUFB (data,(0x0A)-4) = 0x07;
					WBUFW (data,(0x30)-4) = PEntity->look.size;
					memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 12 ? 12 : PEntity->name.size()));
				}
				break;
			}
		}
		break;
	}
}