Exemple #1
0
void CParty::ReloadParty()
{
    auto info = GetPartyInfo();

    //alliance
    if (this->m_PAlliance != nullptr)
    {
        for (auto&& party : m_PAlliance->partyList)
        {
            party->RefreshFlags(info);
            for (auto&& member : party->members)
            {
                CCharEntity* PChar = (CCharEntity*)member;
                PChar->ReloadPartyDec();
                uint16 alliance = 0;
                PChar->pushPacket(new CPartyDefinePacket(party));
                //auto effects = std::make_unique<CPartyEffectsPacket>();
                uint8 j = 0;
                for (auto&& memberinfo : info)
                {
                    if ((memberinfo.flags & (PARTY_SECOND | PARTY_THIRD)) != alliance)
                    {
                        alliance = memberinfo.flags & (PARTY_SECOND | PARTY_THIRD);
                        j = 0;
                    }
                    auto PPartyMember = zoneutils::GetChar(memberinfo.id);
                    if (PPartyMember)
                    {
                        PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, memberinfo.flags, PChar->getZone()));
                        //if (memberinfo.partyid == party->GetPartyID() && PPartyMember != PChar)
                        //    effects->AddMemberEffects(PChar);
                    }
                    else
                    {
                        uint16 zoneid = memberinfo.zone == 0 ? memberinfo.prev_zone : memberinfo.zone;
                        PChar->pushPacket(new CPartyMemberUpdatePacket(
                            memberinfo.id, (const int8*)memberinfo.name.c_str(),
                            memberinfo.flags, j, zoneid));
                    }
                    j++;
                }
                //PChar->pushPacket(effects.release());
            }
        }
    }
    else
    {
        RefreshFlags(info);
        //regular party
        for (uint8 i = 0; i < members.size(); ++i)
        {
            CCharEntity* PChar = (CCharEntity*)members.at(i);

            PChar->PLatentEffectContainer->CheckLatentsPartyJobs();
            PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size());
            PChar->PLatentEffectContainer->CheckLatentsPartyAvatar();
            PChar->ReloadPartyDec();
            PChar->pushPacket(new CPartyDefinePacket(this));
            //auto effects = std::make_unique<CPartyEffectsPacket>();
            uint8 j = 0;
            for (auto&& memberinfo : info)
            {
                auto PPartyMember = zoneutils::GetChar(memberinfo.id);
                if (PPartyMember)
                {
                    PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, memberinfo.flags, PChar->getZone()));
                    //if (PPartyMember != PChar)
                    //    effects->AddMemberEffects(PChar);
                }
                else
                {
                    uint16 zoneid = memberinfo.zone == 0 ? memberinfo.prev_zone : memberinfo.zone;
                    PChar->pushPacket(new CPartyMemberUpdatePacket(
                        memberinfo.id, (const int8*)memberinfo.name.c_str(),
                        memberinfo.flags, j, zoneid));
                    //effects->AddMemberEffects(memberinfo.id);
                }
                j++;
            }
            //PChar->pushPacket(effects.release());
        }
    }
}
Exemple #2
0
int32 map_cleanup(uint32 tick, CTaskMgr::CTask* PTask)
{
	map_session_list_t::iterator it = map_session_list.begin();

	while(it != map_session_list.end())
	{
		map_session_data_t* map_session_data = it->second;

        CCharEntity* PChar = map_session_data->PChar;

        if ((time(NULL) - map_session_data->last_update) > 5)
        {
            if (PChar != NULL && !(PChar->nameflags.flags & FLAG_DC))
            {

                PChar->nameflags.flags |= FLAG_DC;
                if (PChar->status == STATUS_NORMAL)
                {
                    PChar->status = STATUS_UPDATE;
                    PChar->loc.zone->SpawnPCs(PChar);
                }
            }
		    if ((time(NULL) - map_session_data->last_update) > map_config.max_time_lastupdate)
		    {
			    if (PChar != NULL)
			    {

					//[Alliance] fix to stop server crashing:
					//if a party within an alliance only has 1 char (that char will be party leader)
					//if char then disconnects we need to tell the server about the alliance change
					if(PChar->PParty != NULL && PChar->PParty->m_PAlliance != NULL && PChar->PParty->GetLeader() == PChar){
						if(PChar->PParty->members.size() == 1){
							if(PChar->PParty->m_PAlliance->partyList.size() == 2){
								PChar->PParty->m_PAlliance->dissolveAlliance();
							}else if(PChar->PParty->m_PAlliance->partyList.size() == 3){
								PChar->PParty->m_PAlliance->removeParty(PChar->PParty);
								}
						}
					}


					// uncharm pet if player d/c
					if (PChar->PPet != NULL && PChar->PPet->objtype == TYPE_MOB)
						petutils::DespawnPet(PChar);


				    ShowDebug(CL_CYAN"map_cleanup: %s timed out, closing session\n" CL_RESET, PChar->GetName());

				    PChar->status = STATUS_SHUTDOWN;
                    PacketParser[0x00D](map_session_data, PChar, 0);
			    } else if(!map_session_data->shuttingDown){

				    ShowWarning(CL_YELLOW"map_cleanup: WHITHOUT CHAR timed out, session closed\n" CL_RESET);

				    const int8* Query = "DELETE FROM accounts_sessions WHERE client_addr = %u AND client_port = %u";
				    Sql_Query(SqlHandle, Query, map_session_data->client_addr, map_session_data->client_port);

				    aFree(map_session_data->server_packet_data);
				    map_session_list.erase(it++);
                    delete map_session_data;
				    continue;
			    }
		    }
        }
        else if (PChar != NULL && (PChar->nameflags.flags & FLAG_DC))
        {
            PChar->nameflags.flags &= ~FLAG_DC;
            PChar->pushPacket(new CCharUpdatePacket(PChar));

            if (PChar->status == STATUS_NORMAL)
            {
                PChar->status = STATUS_UPDATE;
                PChar->loc.zone->SpawnPCs(PChar);
            }
            charutils::SaveCharStats(PChar);
        }
		++it;
	}
	return 0;
}
Exemple #3
0
void CParty::RemoveMember(CBattleEntity* PEntity)
{
    DSP_DEBUG_BREAK_IF(PEntity == nullptr);
    DSP_DEBUG_BREAK_IF(PEntity->PParty != this);

    if (m_PLeader == PEntity)
    {
        RemovePartyLeader(PEntity);
    }
    else
    {
        for (uint32 i = 0; i < members.size(); ++i)
        {
            if (PEntity == members.at(i))
            {
                members.erase(members.begin() + i);

                if (m_PartyType == PARTY_PCS)
                {
                    CCharEntity* PChar = (CCharEntity*)PEntity;

                    if (m_PQuaterMaster == PChar)
                    {
                        SetQuarterMaster(nullptr);
                    }
                    if (m_PSyncTarget == PChar)
                    {
                        SetSyncTarget(nullptr, 553);
                        CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC);
                        if (sync && sync->GetDuration() == 0)
                        {
                            PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553));
                            sync->SetStartTime(server_clock::now());
                            sync->SetDuration(30000);
                        }
                        DisableSync();
                    }
                    if (m_PSyncTarget != nullptr && m_PSyncTarget != PChar)
                    {
                        if (PChar->status != STATUS_DISAPPEAR)
                        {
                            CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC);
                            if (sync && sync->GetDuration() == 0)
                            {
                                PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553));
                                sync->SetStartTime(server_clock::now());
                                sync->SetDuration(30000);
                            }
                        }
                    }
                    PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size());

                    PChar->pushPacket(new CPartyDefinePacket(nullptr));
                    PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, 0, PChar->getZone()));
                    PChar->pushPacket(new CCharUpdatePacket(PChar));
                    PChar->PParty = nullptr;

                    Sql_Query(SqlHandle, "DELETE FROM accounts_parties WHERE charid = %u;", PChar->id);

                    uint8 data[4] {};
                    ref<uint32>(data, 0) = m_PartyID;
                    message::send(MSG_PT_RELOAD, data, sizeof data, nullptr);

                    if (PChar->PTreasurePool != nullptr &&
                        PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE)
                    {
                        PChar->PTreasurePool->DelMember(PChar);
                        PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO);
                        PChar->PTreasurePool->AddMember(PChar);
                        PChar->PTreasurePool->UpdatePool(PChar);
                    }
                }
                break;
            }
        }
    }
}
Exemple #4
0
void CZoneEntities::PushPacket(CBaseEntity* PEntity, GLOBAL_MESSAGE_TYPE message_type, CBasicPacket* packet)
{
    if (!packet) { return; }
    // Do not send packets that are updates of a hidden GM..
    if (packet->id() == 0x00D && PEntity != nullptr && PEntity->objtype == TYPE_PC && ((CCharEntity*)PEntity)->m_isGMHidden)
    {
        // Ensure this packet is not despawning us..
        if (packet->ref<uint8>(0x0A) != 0x20)
        {
            delete packet;
            return;
        }
    }

    if (!m_charList.empty())
    {
        switch (message_type)
        {
            case CHAR_INRANGE_SELF:
            {
                if (PEntity->objtype == TYPE_PC)
                {
                    ((CCharEntity*)PEntity)->pushPacket(new CBasicPacket(*packet));
                }
            }
            case CHAR_INRANGE:
            {
                // todo: rewrite packet handlers and use enums instead of rawdog packet ids
                // 30 yalms if action packet, 50 otherwise
                const int checkDistanceSq = packet->id() == 0x0028 ? 900 : 2500;

                for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
                {
                    CCharEntity* PCurrentChar = (CCharEntity*)it->second;
                    if (PEntity != PCurrentChar)
                    {
                        if (distanceSquared(PEntity->loc.p, PCurrentChar->loc.p) < checkDistanceSq &&
                            ((PEntity->objtype != TYPE_PC) || (((CCharEntity*)PEntity)->m_moghouseID == PCurrentChar->m_moghouseID)))
                        {
                            if (packet->id() == 0x00E &&
                                (packet->ref<uint8>(0x0A) != 0x20 || packet->ref<uint8>(0x0A) != 0x0F))
                            {
                                uint32 id = packet->ref<uint32>(0x04);
                                uint16 targid = packet->ref<uint16>(0x08);

                                CBaseEntity* entity = GetEntity(targid);

                                SpawnIDList_t spawnlist;

                                if (entity)
                                {
                                    if (entity->targid < 0x400)
                                    {
                                        if (entity->objtype == TYPE_MOB)
                                        {
                                            spawnlist = PCurrentChar->SpawnMOBList;
                                        }
                                        else if (entity->objtype == TYPE_NPC)
                                        {
                                            spawnlist = PCurrentChar->SpawnNPCList;
                                        }
                                    }
                                    else if (entity->targid >= 0x700)
                                    {
                                        spawnlist = PCurrentChar->SpawnPETList;
                                    }
                                    else
                                    {
                                        entity = nullptr;
                                    }
                                }
                                if (!entity)
                                {
                                    // got a char or nothing as the target of this entity update (which really shouldn't happen ever)
                                    // so we're just going to skip this packet
                                    break;
                                }
                                SpawnIDList_t::iterator iter = spawnlist.lower_bound(id);

                                if (!(iter == spawnlist.end() ||
                                    spawnlist.key_comp()(id, iter->first)))
                                {
                                    PCurrentChar->pushPacket(new CBasicPacket(*packet));
                                }
                            }
                            else
                            {
                                PCurrentChar->pushPacket(new CBasicPacket(*packet));
                            }
                        }
                    }
                }
            }
            break;
            case CHAR_INSHOUT:
            {
                for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
                {
                    CCharEntity* PCurrentChar = (CCharEntity*)it->second;
                    if (PEntity != PCurrentChar)
                    {
                        if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 180 &&
                            ((PEntity->objtype != TYPE_PC) || (((CCharEntity*)PEntity)->m_moghouseID == PCurrentChar->m_moghouseID)))
                        {
                            PCurrentChar->pushPacket(new CBasicPacket(*packet));
                        }
                    }
                }
            }
            break;
            case CHAR_INZONE:
            {
                for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
                {
                    CCharEntity* PCurrentChar = (CCharEntity*)it->second;

                    if (PCurrentChar->m_moghouseID == 0)
                    {
                        if (PEntity != PCurrentChar)
                        {
                            PCurrentChar->pushPacket(new CBasicPacket(*packet));
                        }
                    }
                }
            }
            break;
        }
    }
    delete packet;
}
Exemple #5
0
int32 parse(int8* buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data)
{
	// начало обработки входящего пакета

	int8* PacketData_Begin = &buff[FFXI_HEADER_SIZE];
	int8* PacketData_End   = &buff[*buffsize];

	CCharEntity *PChar = map_session_data->PChar;

	uint16 SmallPD_Size = 0;
	uint16 SmallPD_Type = 0;
	uint16 SmallPD_Code = RBUFW(buff,0);

	for(int8* SmallPD_ptr = PacketData_Begin;
		SmallPD_ptr + (RBUFB(SmallPD_ptr,1) & 0xFE)*2 <= PacketData_End && (RBUFB(SmallPD_ptr,1) & 0xFE);
		SmallPD_ptr = SmallPD_ptr + SmallPD_Size*2)
	{
		SmallPD_Size = (RBUFB(SmallPD_ptr,1) & 0x0FE);
		SmallPD_Type = (RBUFW(SmallPD_ptr,0) & 0x1FF);

		if(PacketSize[SmallPD_Type] == SmallPD_Size || PacketSize[SmallPD_Type] == 0) // Tests incoming packets for the correct size prior to processing
		{
            // если код текущего пакета меньше либо равен последнему полученному
		    // или больше глобального то игнорируем пакет

			if ((RBUFW(SmallPD_ptr,2) <= map_session_data->client_packet_id) ||
				(RBUFW(SmallPD_ptr,2) >  SmallPD_Code))
			{
				continue;
			}
			if (SmallPD_Type != 0x15)
			{
				ShowInfo("parse: %03hX | %04hX %04hX %02hX from user: %s\n", SmallPD_Type, RBUFW(SmallPD_ptr,2), RBUFW(buff,2), SmallPD_Size, PChar->GetName());
			}
			if (PChar->loc.zone == NULL && SmallPD_Type != 0x0A)
            {
				ShowWarning("This packet is unexpected from %s - Received %03hX earlier without matching 0x0A\n", PChar->GetName(), SmallPD_Type);
			}
			else
            {
				PacketParser[SmallPD_Type](map_session_data, PChar, SmallPD_ptr);
			}
        }
        else
        {
            ShowWarning("Bad packet size %03hX | %04hX %04hX %02hX from user: %s\n", SmallPD_Type, RBUFW(SmallPD_ptr,2), RBUFW(buff,2), SmallPD_Size, PChar->GetName());
        }
	}
    map_session_data->client_packet_id = SmallPD_Code;

	// здесь мы проверяем, получил ли клиент предыдущий пакет
	// если не получил, то мы не создаем новый, а отправляем предыдущий

	if (RBUFW(buff,2) != map_session_data->server_packet_id)
	{
		WBUFW(map_session_data->server_packet_data,2) = SmallPD_Code;
		WBUFW(map_session_data->server_packet_data,8) = (uint32)time(NULL);

		g_PBuff	 = map_session_data->server_packet_data;
	   *buffsize = map_session_data->server_packet_size;

		map_session_data->server_packet_data = buff;
		return -1;
	}

	// увеличиваем номер отправленного пакета только в случае отправки новых данных

	map_session_data->server_packet_id += 1;

	// собираем большой пакет, состоящий из нескольких маленьких

	CBasicPacket* PSmallPacket;

	*buffsize = FFXI_HEADER_SIZE;

	while(!PChar->isPacketListEmpty() && *buffsize + PChar->firstPacketSize()*2 < map_config.buffer_size )
	{
		PSmallPacket = PChar->popPacket();

		PSmallPacket->setCode(map_session_data->server_packet_id);
		memcpy(buff+*buffsize, PSmallPacket, PSmallPacket->getSize()*2);

		*buffsize += PSmallPacket->getSize()*2;

		delete PSmallPacket;
	}
	return 0;
}
void CStatusEffectContainer::CheckRegen(uint32 tick)
{
	DSP_DEBUG_BREAK_IF(m_POwner == nullptr);

	if (!m_POwner->isDead())
	{
		if ((tick - m_RegenCheckTime) < 3000 )
		{
			return;
		}

        CCharEntity* PChar = nullptr;
        if(m_POwner->objtype == TYPE_PC)
        {
            PChar = (CCharEntity*)m_POwner;
        }

		m_RegenCheckTime = tick;

        int16 regen = m_POwner->getMod(MOD_REGEN);
        int16 poison = m_POwner->getMod(MOD_REGEN_DOWN);
        int16 refresh = m_POwner->getMod(MOD_REFRESH) - m_POwner->getMod(MOD_REFRESH_DOWN);
        int16 regain = m_POwner->getMod(MOD_REGAIN) - m_POwner->getMod(MOD_REGAIN_DOWN);
        bool update = false;
        if (m_POwner->addHP(regen))
            update = true;

        if(poison)
        {
            int16 damage = battleutils::HandleStoneskin(m_POwner, poison);

            if(damage > 0)
            {
                DelStatusEffectSilent(EFFECT_HEALING);
                m_POwner->addHP(-damage);
                WakeUp();
                update = true;
            }
        }

		if (m_POwner->getMod(MOD_AVATAR_PERPETUATION) > 0 && (m_POwner->objtype == TYPE_PC))
		{
			int16 perpetuation = m_POwner->getMod(MOD_AVATAR_PERPETUATION);

			if (m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_ASTRAL_FLOW))
				perpetuation = 0;
			else
			{
				if (m_POwner->PPet != nullptr && PChar != nullptr)
				{

                    if(m_POwner->PPet->objtype == TYPE_PET)
                    {

                        CPetEntity* PPet = (CPetEntity*)m_POwner->PPet;
    					CItem* hands = PChar->getEquip(SLOT_HANDS);

                        // carbuncle mitts only work on carbuncle
    					if (hands && hands->getID() == 14062 && PPet->name == "Carbuncle"){
    						perpetuation /= 2;
    					}
                    }


					perpetuation -= charutils::AvatarPerpetuationReduction(PChar);

					if( perpetuation < 1 )
						perpetuation = 1;
				}
			}

            if (m_POwner->addMP(refresh - perpetuation))
                update = true;

			if( m_POwner->health.mp == 0 && m_POwner->PPet != nullptr && m_POwner->PPet->objtype == TYPE_PET)
			{
				CPetEntity* PPet = (CPetEntity*)m_POwner->PPet;
				if (PPet->getPetType() == PETTYPE_AVATAR) {
					petutils::DespawnPet(m_POwner);
				}
			}
		}
		else
		{
            if (m_POwner->addMP(refresh))
                update = true;
		}

        if (m_POwner->addTP(regain))
            update = true;

        if (m_POwner->PPet && ((CPetEntity*)(m_POwner->PPet))->getPetType() == PETTYPE_AUTOMATON)
        {
            ((CAutomatonEntity*)(m_POwner->PPet))->burdenTick();
        }

		if( m_POwner->status != STATUS_DISAPPEAR && (m_POwner->objtype == TYPE_PC) && update)
		{
			charutils::UpdateHealth((CCharEntity*)m_POwner);
		}
    }
}
Exemple #7
0
void CZone::DecreaseZoneCounter(CCharEntity* PChar)
{
    DSP_DEBUG_BREAK_IF(PChar == NULL);
    DSP_DEBUG_BREAK_IF(PChar->loc.zone != this);

	//remove pets
	if(PChar->PPet != NULL)
    {
		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 nulled by DespawnPet
		if(PChar->PPet != NULL) {
			PChar->PPet->PBattleAI->SetCurrentAction(ACTION_NONE);
			DeletePET(PChar->PPet);//remove the TID for this pet

			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));
				}
			}
			PChar->PPet = NULL;
		}
	}

	//remove bcnm status
	if(m_InstanceHandler != NULL && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_BATTLEFIELD))
    {
		if(m_InstanceHandler->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};
			instanceutils::getStartPosition(m_zoneID,pos);
			if(pos!=NULL){
				PChar->loc.p.x = pos[0];
				PChar->loc.p.y = pos[1];
				PChar->loc.p.z = pos[2];
				PChar->loc.p.rotation = pos[3];
				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_InstanceHandler != NULL && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DYNAMIS, 0))
    {
		if(m_InstanceHandler->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};
			instanceutils::getStartPosition(m_zoneID,pos);
			if(pos!=NULL){
				PChar->loc.p.x = pos[0];
				PChar->loc.p.y = pos[1];
				PChar->loc.p.z = pos[2];
				PChar->loc.p.rotation = pos[3];
				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 (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it)
	{
		CMobEntity* PCurrentMob = (CMobEntity*)it->second;
		PCurrentMob->PEnmityContainer->Clear(PChar->id);
		if(PCurrentMob->m_OwnerID.id == PChar->id){
			PCurrentMob->m_OwnerID.clean();
		}
	}

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

	m_charList.erase(PChar->targid);

	ShowDebug(CL_CYAN"CZone:: %s DecreaseZoneCounter <%u> %s\n" CL_RESET, GetName(), m_charList.size(),PChar->GetName());

	if (ZoneTimer && m_charList.empty())
	{
		ZoneTimer->m_type = CTaskMgr::TASK_REMOVE;
		ZoneTimer = NULL;

    HealAllMobs();
	}
	else
	{
		for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it)
		{
			CCharEntity* PCurrentChar = (CCharEntity*)it->second;
			SpawnIDList_t::iterator PC = PCurrentChar->SpawnPCList.find(PChar->id);

			if( PC != PCurrentChar->SpawnPCList.end() )
			{
				PCurrentChar->SpawnPCList.erase(PC);
				PCurrentChar->pushPacket(new CCharPacket(PChar,ENTITY_DESPAWN));
			}
		}
	}
	if (PChar->m_LevelRestriction != 0)
	{
		PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_SYNC);
		PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_RESTRICTION);
	}
	if (PChar->PTreasurePool != NULL) // TODO: условие для устранения проблем с MobHouse, надо блин решить ее раз и навсегда
	{
		PChar->PTreasurePool->DelMember(PChar);
	}
    for (regionList_t::const_iterator region = m_regionList.begin(); region != m_regionList.end(); ++region)
    {
        if ((*region)->GetRegionID() == PChar->m_InsideRegionID)
        {
            luautils::OnRegionLeave(PChar, *region);
            break;
        }
    }

    PChar->loc.zone = NULL;
    PChar->loc.prevzone = m_zoneID;

    PChar->SpawnPCList.clear();
	PChar->SpawnNPCList.clear();
	PChar->SpawnMOBList.clear();
	PChar->SpawnPETList.clear();
}
Exemple #8
0
void CParty::SetSyncTarget(CBattleEntity* PEntity, uint16 message)
{
    if (map_config.level_sync_enable)
    {
        if (PEntity && PEntity->objtype == TYPE_PC)
        {
            CCharEntity* PChar = (CCharEntity*)PEntity;
            //enable level sync
            if (PChar->GetMLevel() < 10 )
            {
                ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 10, 541));
                return;
            }
            else if (PChar->getZone() != GetLeader()->getZone())
            {
                ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 542));
                return;
            }
            else
            {
                for (uint32 i = 0; i < members.size(); ++i)
                {
                    if(members.at(i)->StatusEffectContainer->HasStatusEffect(EFFECT_LEVEL_RESTRICTION))
                    {
                        ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 543));
                        return;
                    }
                }
                m_PSyncTarget = PChar;
	            for (uint32 i = 0; i < members.size(); ++i)
	            {
		            if(members.at(i)->objtype != TYPE_PC) continue;

		            CCharEntity* member = (CCharEntity*)members.at(i);

                    if (member->status != STATUS_DISAPPEAR &&
                         member->getZone() == PChar->getZone() )
		            {
			            member->pushPacket(new CMessageStandardPacket(PChar->GetMLevel(), 0, 0, 0, message));
                        member->StatusEffectContainer->AddStatusEffect(new CStatusEffect(
                            EFFECT_LEVEL_SYNC,
                            EFFECT_LEVEL_SYNC,
                            PChar->GetMLevel(),
                            0,
                            0), true);
                        member->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE);
                        member->loc.zone->PushPacket(member, CHAR_INRANGE, new CCharSyncPacket(member));
		            }
	            }
            }
        }
        else
        {
            if (m_PSyncTarget != NULL)
            {
                //disable level sync
                for (uint32 i = 0; i < members.size(); ++i)
	            {
		            if(members.at(i)->objtype != TYPE_PC) continue;

		            CCharEntity* member = (CCharEntity*)members.at(i);

                    if (member->status != STATUS_DISAPPEAR &&
                         member->getZone() == m_PSyncTarget->getZone() )
		            {
                        CStatusEffect* sync = member->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC);
                        if (sync && sync->GetDuration() == 0)
                        {
			                member->pushPacket(new CMessageBasicPacket(member, member, 10, 30, message));
                            sync->SetStartTime(gettick());
                            sync->SetDuration(30000);
                        }
		            }
	            }
            }
        }
    }
}
/************************************************************************
* *
* Tick regen/refresh/regain effects *
* *
************************************************************************/
void CStatusEffectContainer::CheckRegen(uint32 tick)
{
DSP_DEBUG_BREAK_IF(m_POwner == NULL);
if (!m_POwner->isDead())
{
if ((tick - m_RegenCheckTime) < 3000 )
{
return;
}
CCharEntity* PChar = NULL;
if(m_POwner->objtype == TYPE_PC)
{
PChar = (CCharEntity*)m_POwner;
}
m_RegenCheckTime = tick;
int8 regen = m_POwner->getMod(MOD_REGEN);
int8 poison = m_POwner->getMod(MOD_REGEN_DOWN);
int8 refresh = m_POwner->getMod(MOD_REFRESH) - m_POwner->getMod(MOD_REFRESH_DOWN);
int16 regain = m_POwner->getMod(MOD_REGAIN) - m_POwner->getMod(MOD_REGAIN_DOWN);
m_POwner->addHP(regen);
if(poison)
{
int16 damage = battleutils::HandleStoneskin(m_POwner, poison);
if(damage > 0)
{
DelStatusEffectSilent(EFFECT_HEALING);
m_POwner->addHP(-damage);
WakeUp();
}
}
if (m_POwner->getMod(MOD_AVATAR_PERPETUATION) > 0 && (m_POwner->objtype == TYPE_PC))
{
int8 perpetuation = m_POwner->getMod(MOD_AVATAR_PERPETUATION);
if (m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_ASTRAL_FLOW))
perpetuation = 0;
else
{
if (m_POwner->PPet != NULL && PChar != NULL)
{
if(m_POwner->PPet->objtype == TYPE_PET)
{
CPetEntity* PPet = (CPetEntity*)m_POwner->PPet;
CItem* hands = PChar->getEquip(SLOT_HANDS);
// carbuncle mitts only work on carbuncle
if (hands && hands->getID() == 14062 && PPet->name == "Carbuncle"){
perpetuation /= 2;
}
}
perpetuation -= charutils::AvatarPerpetuationReduction(PChar);
if( perpetuation < 1 )
perpetuation = 1;
}
}
m_POwner->addMP(refresh - perpetuation);
if( m_POwner->health.mp == 0 && m_POwner->PPet != NULL && m_POwner->PPet->objtype == TYPE_PET)
{
CPetEntity* PPet = (CPetEntity*)m_POwner->PPet;
if (PPet->getPetType() == PETTYPE_AVATAR) {
petutils::DespawnPet(m_POwner);
}
}
}
else
{
m_POwner->addMP(refresh);
}
if(PChar != NULL && IsAsleep())
{
CItem* neck = PChar->getEquip(SLOT_NECK);
// opo-opo necklace
if(neck != NULL && neck->getID() == 13143)
{
// add tp
regain += 2.5f;
}
}
m_POwner->addTP(regain);
if( m_POwner->status != STATUS_DISAPPEAR && (m_POwner->objtype == TYPE_PC))
{
charutils::UpdateHealth((CCharEntity*)m_POwner);
}
}
}
Exemple #10
0
void CLinkshell::RemoveMemberByName(int8* MemberName)
{
	for (uint32 i = 0; i < members.size(); ++i) 
	{
		if (strcmp(MemberName, members.at(i)->GetName()) == 0)
		{
            CCharEntity* PMember = (CCharEntity*)members.at(i);

            CItemLinkshell* PItemLinkshell = (CItemLinkshell*)PMember->getEquip(SLOT_LINK1);
            SLOTTYPE slot = SLOT_LINK1;
            int lsNum = 1;

            if (PItemLinkshell->GetLSID() != this->getID())
            {
                PItemLinkshell = (CItemLinkshell*)PMember->getEquip(SLOT_LINK2);
                slot = SLOT_LINK2;
                lsNum = 2;
            }

            if (PItemLinkshell != nullptr && PItemLinkshell->isType(ITEM_LINKSHELL))
            {
                linkshell::DelOnlineMember(PMember, PItemLinkshell);

                PItemLinkshell->setSubType(ITEM_UNLOCKED);

                PMember->equip[slot] = 0;
                if (slot == SLOT_LINK1)
                {
                    PMember->nameflags.flags &= ~FLAG_LINKSHELL;
                    PMember->updatemask |= UPDATE_HP;
                }

                PMember->pushPacket(new CInventoryAssignPacket(PItemLinkshell, INV_NORMAL));
                PMember->pushPacket(new CLinkshellEquipPacket(PMember,lsNum));
            }

			CItemContainer* Inventory = PMember->getStorage(LOC_INVENTORY);
            for (uint8 SlotID = 0; SlotID < Inventory->GetSize(); ++SlotID)
            {
                    CItemLinkshell* PItemLinkshell = (CItemLinkshell*)Inventory->GetItem(SlotID);

					if (PItemLinkshell != nullptr && PItemLinkshell->isType(ITEM_LINKSHELL) && PItemLinkshell->GetLSID() == m_id)
		            {
                        const int8* Query = "UPDATE char_inventory SET itemid = (itemid+2) WHERE charid = %u AND location = %u AND slot = %u LIMIT 1";

                        Sql_Query(SqlHandle, Query, PMember->id, LOC_INVENTORY, SlotID);

                        PItemLinkshell->SetLSID(0);
                        PItemLinkshell->setID(PItemLinkshell->getID() + 2);

                        PMember->pushPacket(new CInventoryItemPacket(PItemLinkshell, LOC_INVENTORY, SlotID));
		            }
            }
	        
            charutils::SaveCharStats(PMember);
            charutils::SaveCharEquip(PMember);

            PMember->pushPacket(new CInventoryFinishPacket());
            PMember->pushPacket(new CCharUpdatePacket(PMember));
            PMember->pushPacket(new CMessageSystemPacket(0,0,109));
			return;
		} 
	}
}
Exemple #11
0
void CParty::ReloadParty()
{
    //check if partyflags have changed
    int ret = Sql_Query(SqlHandle, "SELECT charid, partyflag FROM accounts_parties WHERE partyid = %d;", m_PartyID);

    if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) > 0)
    {
        uint8 j = 0;
        while (Sql_NextRow(SqlHandle) == SQL_SUCCESS)
        {
            uint32 charid = Sql_GetUIntData(SqlHandle, 0);
            uint16 memberflags = Sql_GetUIntData(SqlHandle, 1);

            if (memberflags & PARTY_LEADER)
            {
                bool found = false;
                for (auto member : members)
                {
                    if (member->id == charid)
                    {
                        m_PLeader = member;
                        found = true;
                    }
                }
                if (!found)
                {
                    m_PLeader = nullptr;
                }
            }
            if (memberflags & PARTY_QM)
            {
                bool found = false;
                for (auto member : members)
                {
                    if (member->id == charid)
                    {
                        m_PQuaterMaster = member;
                        found = true;
                    }
                }
                if (!found)
                {
                    m_PQuaterMaster = nullptr;
                }
            }
            if (memberflags & ALLIANCE_LEADER && m_PAlliance)
            {
                bool found = false;
                for (auto member : members)
                {
                    if (member->id == charid)
                    {
                        m_PAlliance->setMainParty(this);
                        found = true;
                    }
                }
                if (!found)
                {
                    m_PAlliance->setMainParty(nullptr);
                }
            }
        }
    }
	//alliance
	if (this->m_PAlliance != nullptr)
	{
		for (uint8 a = 0; a < m_PAlliance->partyList.size(); ++a)
		{
			for (uint8 i = 0; i < m_PAlliance->partyList.at(a)->members.size(); ++i)
			{
				CCharEntity* PChar = (CCharEntity*)m_PAlliance->partyList.at(a)->members.at(i);
                PChar->ReloadPartyDec();
				uint16 alliance = 0;
				PChar->pushPacket(new CPartyDefinePacket(m_PAlliance->partyList.at(a)));
				int ret = Sql_Query(SqlHandle, "SELECT chars.charid, chars.charname, partyflag, pos_zone, pos_prevzone FROM accounts_parties \
												LEFT JOIN chars ON accounts_parties.charid = chars.charid WHERE \
												allianceid = %d ORDER BY partyflag & %u, timestamp;",
												m_PAlliance->m_AllianceID, PARTY_SECOND | PARTY_THIRD);
				if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) > 0)
				{
					uint8 j = 0;
					while (Sql_NextRow(SqlHandle) == SQL_SUCCESS)
					{
						if ((Sql_GetUIntData(SqlHandle, 2) & (PARTY_SECOND | PARTY_THIRD)) != alliance)
						{
							alliance = Sql_GetUIntData(SqlHandle, 2) & (PARTY_SECOND | PARTY_THIRD);
							j = 0;
						}
						CCharEntity* PPartyMember = zoneutils::GetChar(Sql_GetUIntData(SqlHandle, 0));
						if (PPartyMember)
						{
							PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, PChar->getZone()));
						}
						else
						{
                            uint16 zoneid = Sql_GetUIntData(SqlHandle, 3) == 0 ? Sql_GetUIntData(SqlHandle, 4) : Sql_GetUIntData(SqlHandle, 3);
							PChar->pushPacket(new CPartyMemberUpdatePacket(
								Sql_GetUIntData(SqlHandle, 0), Sql_GetData(SqlHandle, 1),
								Sql_GetUIntData(SqlHandle, 2), zoneid));
						}
						j++;
					}
				}
			}
		}
	}
	else

	//regular party
	for (uint8 i = 0; i < members.size(); ++i)
Exemple #12
0
void CLinkshell::ChangeMemberRank(int8* MemberName, uint8 toSack)
{
	//topearl = 3
	//tosack = 2
	int newId = 512 + toSack;
	
    if (newId == 514 || newId == 515)
    {
	    for (uint32 i = 0; i < members.size(); ++i) 
	    {
		    if (strcmp(MemberName, members.at(i)->GetName()) == 0)
		    {
                CCharEntity* PMember = (CCharEntity*)members.at(i);

                SLOTTYPE slot = SLOT_LINK1;
                int lsID = 1;
                if (PMember->PLinkshell2 == this)
                {
                    lsID = 2;
                    slot = SLOT_LINK2;
                }

                CItemLinkshell* PItemLinkshell = (CItemLinkshell*)PMember->getEquip(slot);

                if (PItemLinkshell != nullptr && PItemLinkshell->isType(ITEM_LINKSHELL))
                {
				    PItemLinkshell->setID(newId);

                    PMember->pushPacket(new CInventoryAssignPacket(PItemLinkshell, INV_NORMAL));
                    PMember->pushPacket(new CLinkshellEquipPacket(PMember, lsID));
                }

			    CItemContainer* Inventory = PMember->getStorage(LOC_INVENTORY);
                for (uint8 SlotID = 0; SlotID < Inventory->GetSize(); ++SlotID)
                {
                        CItemLinkshell* PItemLinkshell = (CItemLinkshell*)Inventory->GetItem(SlotID);

					    if (PItemLinkshell != nullptr && PItemLinkshell->isType(ITEM_LINKSHELL) && PItemLinkshell->GetLSID() == m_id)
		                {
                            const int8* Query = "UPDATE char_inventory SET itemid = %u WHERE charid = %u AND location = %u AND slot = %u LIMIT 1";
						    Sql_Query(SqlHandle, Query, PItemLinkshell->getID(),PMember->id, LOC_INVENTORY, SlotID);
                            if (lsID == 1)
                            {
                                Sql_Query(SqlHandle, "UPDATE accounts_sessions SET linkshellid1 = %u , linkshellrank1 = %u WHERE charid = %u",
                                    m_id, PItemLinkshell->GetLSType(), PMember->id);
                            }
                            else if (lsID == 2)
                            {
                                Sql_Query(SqlHandle, "UPDATE accounts_sessions SET linkshellid2 = %u , linkshellrank2 = %u WHERE charid = %u",
                                    m_id, PItemLinkshell->GetLSType(), PMember->id);
                            }
                            PMember->pushPacket(new CInventoryItemPacket(PItemLinkshell, LOC_INVENTORY, SlotID));
		                }
                }
	        
                charutils::SaveCharStats(PMember);
                charutils::SaveCharEquip(PMember);

                PMember->pushPacket(new CInventoryFinishPacket());
                PMember->pushPacket(new CCharUpdatePacket(PMember));
			    return;
		    } 
	    }
    }
}
bool CStatusEffectContainer::AddStatusEffect(CStatusEffect* PStatusEffect, bool silent)
{
    if(PStatusEffect == NULL){
        ShowWarning("status_effect_container::AddStatusEffect Status effect given was NULL!\n");
        return false;
    }

    uint16 statusId = PStatusEffect->GetStatusID();

    if(statusId >= MAX_EFFECTID){
        ShowWarning("status_effect_container::AddStatusEffect statusId given is OVER limit %d\n", statusId);
        return false;
    }

	if(CanGainStatusEffect((EFFECT)statusId, PStatusEffect->GetPower()))
	{
        // remove clean up other effects
        OverwriteStatusEffect(PStatusEffect);

        PStatusEffect->SetOwner(m_POwner);

        SetEffectParams(PStatusEffect);

        // remove effects with same type
        DelStatusEffectsByType(PStatusEffect->GetType());

        PStatusEffect->SetStartTime(gettick());

        m_StatusEffectList.push_back(PStatusEffect);

        luautils::OnEffectGain(m_POwner, PStatusEffect);

        m_POwner->addModifiers(&PStatusEffect->modList);

        if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in
        {
            m_POwner->UpdateHealth();
        }

        if (m_POwner->objtype == TYPE_PC)
        {
            CCharEntity* PChar = (CCharEntity*)m_POwner;

            if (PStatusEffect->GetIcon() != 0)
            {
                UpdateStatusIcons();
            }
            if (PChar->status == STATUS_NORMAL) PChar->status = STATUS_UPDATE;

			if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in
			{
				//check for latents
				CLatentEffectContainer* PLatentEffectContainer;
				PChar->PLatentEffectContainer->CheckLatentsFoodEffect();
				PChar->PLatentEffectContainer->CheckLatentsStatusEffect();
				PChar->UpdateHealth();

				PChar->pushPacket(new CCharHealthPacket(PChar));
			}
            PChar->pushPacket(new CCharSyncPacket(PChar));
        }

        return true;
	}

    return false;
}
Exemple #14
0
/************************************************************************
*                                                                       *
*  Creates up to many attacks for a particular hand.			        *
*                                                                       *
************************************************************************/
void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction)
{
    uint8 num = 1;

    bool isPC = m_attacker->objtype == TYPE_PC;

    // Checking the players weapon hit count
    if (PWeapon->getReqLvl() <= m_attacker->GetMLevel())
    {
        num = PWeapon->getHitCount();
    }

    // If the attacker is a mobentity or derived from mobentity, check to see if it has any special mutli-hit capabilties
    if (dynamic_cast<CMobEntity*>(m_attacker))
    {
        auto multiHitMax = (uint8)static_cast<CMobEntity*>(m_attacker)->getMobMod(MOBMOD_MULTI_HIT);

        if (multiHitMax > 0)
            num = 1 + battleutils::getHitCount(multiHitMax);
    }

    AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, num);

    // Checking the players triple, double and quadruple attack
    int16 tripleAttack = m_attacker->getMod(Mod::TRIPLE_ATTACK);
    int16 doubleAttack = m_attacker->getMod(Mod::DOUBLE_ATTACK);
    int16 quadAttack = m_attacker->getMod(Mod::QUAD_ATTACK);

    //check for merit upgrades
    if (isPC)
    {
        CCharEntity* PChar = (CCharEntity*)m_attacker;

        //merit chance only applies if player has the job trait
        if (charutils::hasTrait(PChar, TRAIT_TRIPLE_ATTACK)) tripleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_TRIPLE_ATTACK_RATE, PChar);

        // Ambush Augment adds +1% Triple Attack per merit (need to satisfy conditions for Ambush)
        if (charutils::hasTrait(PChar, TRAIT_AMBUSH) && PChar->getMod(Mod::AUGMENTS_AMBUSH) > 0 && abs(m_defender->loc.p.rotation - m_attacker->loc.p.rotation) < 23)
        {
            tripleAttack += PChar->PMeritPoints->GetMerit(MERIT_AMBUSH)->count;
        }

        if (charutils::hasTrait(PChar, TRAIT_DOUBLE_ATTACK)) doubleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_DOUBLE_ATTACK_RATE, PChar);
        // TODO: Quadruple attack merits when SE release them.
    }

    quadAttack = std::clamp<int16>(quadAttack, 0, 100);
    doubleAttack = std::clamp<int16>(doubleAttack, 0, 100);
    tripleAttack = std::clamp<int16>(tripleAttack, 0, 100);

    // Checking Mikage Effect - Hits Vary With Num of Utsusemi Shadows for Main Weapon
    if (m_attacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIKAGE) && m_attacker->m_Weapons[SLOT_MAIN]->getID() == PWeapon->getID())
    {
        auto shadows = (uint8)m_attacker->getMod(Mod::UTSUSEMI);
        //ShowDebug(CL_CYAN"Create Attacks: Mikage Active, Rolling Attack Chance for %d Shadowss...\n" CL_RESET, shadows);
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, shadows);
    }
    else if (num == 1 && dsprand::GetRandomNumber(100) < quadAttack)
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::QUAD, direction, 3);

    else if (num == 1 && dsprand::GetRandomNumber(100) < tripleAttack)
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::TRIPLE, direction, 2);

    else if (num == 1 && dsprand::GetRandomNumber(100) < doubleAttack)
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::DOUBLE, direction, 1);

    // Apply Mythic OAT mods (mainhand only)
    if (direction == PHYSICAL_ATTACK_DIRECTION::RIGHTATTACK)
    {
        int16 occAttThriceRate = std::clamp<int16>(m_attacker->getMod(Mod::MYTHIC_OCC_ATT_THRICE), 0, 100);
        int16 occAttTwiceRate = std::clamp<int16>(m_attacker->getMod(Mod::MYTHIC_OCC_ATT_TWICE), 0, 100);
        if (num == 1 && dsprand::GetRandomNumber(100) < occAttThriceRate)
        {
            AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, 2);
        }
        else if (num == 1 && dsprand::GetRandomNumber(100) < occAttTwiceRate)
        {
            AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, 1);
        }
    }

    // Ammo extra swing - players only
    if (isPC && m_attacker->getMod(Mod::AMMO_SWING) > 0)
    {
        // Check for ammo
        CCharEntity* PChar = (CCharEntity*)m_attacker;
        CItemArmor* PAmmo = PChar->getEquip(SLOT_AMMO);
        CItemArmor* PMain = PChar->getEquip(SLOT_MAIN);
        CItemArmor* PSub = PChar->getEquip(SLOT_SUB);
        uint8 slot = PChar->equip[SLOT_AMMO];
        uint8 loc = PChar->equipLoc[SLOT_AMMO];
        uint8 ammoCount = 0;

        // Handedness check, checking mod of the weapon for the purposes of level scaling
        if (battleutils::GetScaledItemModifier(PChar, PMain, Mod::AMMO_SWING_TYPE) == 2 &&
            dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity())
        {
            AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, 1);
            ammoCount += 1;
        }
        else
        {
            if (direction == RIGHTATTACK && battleutils::GetScaledItemModifier(PChar, PMain, Mod::AMMO_SWING_TYPE) == 1 &&
                dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity())
            {
                AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, RIGHTATTACK, 1);
                ammoCount += 1;
            }
            if (direction == LEFTATTACK && PSub != nullptr && battleutils::GetScaledItemModifier(PChar, PSub, Mod::AMMO_SWING_TYPE) == 1 &&
                dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity())
            {
                AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, LEFTATTACK, 1);
                ammoCount += 1;
            }
        }

        if (PAmmo != nullptr)
        {
            if (PAmmo->getQuantity() == ammoCount)
            {
                charutils::UnequipItem(PChar, SLOT_AMMO);
                charutils::SaveCharEquip(PChar);
            }
            charutils::UpdateItem(PChar, loc, slot, -ammoCount);
            PChar->pushPacket(new CInventoryFinishPacket());
        }
    }


    // TODO: Possible Lua function for the nitty gritty stuff below.

    // Iga mod: Extra attack chance whilst dual wield is on.
    if (direction == LEFTATTACK && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::EXTRA_DUAL_WIELD_ATTACK))
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, RIGHTATTACK, 1);

}
Exemple #15
0
void CParty::SetSyncTarget(int8* MemberName, uint16 message)
{
    CBattleEntity* PEntity = nullptr;
    if (MemberName)
    {
        PEntity = GetMemberByName(MemberName);
    }

    if (map_config.level_sync_enable)
    {
        if (PEntity && PEntity->objtype == TYPE_PC)
        {
            CCharEntity* PChar = (CCharEntity*)PEntity;
            //enable level sync
            if (PChar->GetMLevel() < 10)
            {
                ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 10, 541));
                return;
            }
            else if (PChar->getZone() != GetLeader()->getZone())
            {
                ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 542));
                return;
            }
            else
            {
                for (uint8 i = 0; i < members.size(); ++i)
                {
                    if (members.at(i)->StatusEffectContainer->HasStatusEffect({EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_SYNC}))
                    {
                        ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 543));
                        return;
                    }
                }
                m_PSyncTarget = PChar;
                for (uint8 i = 0; i < members.size(); ++i)
                {
                    if (members.at(i)->objtype != TYPE_PC) continue;

                    CCharEntity* member = (CCharEntity*)members.at(i);

                    if (member->status != STATUS_DISAPPEAR &&
                        member->getZone() == PChar->getZone())
                    {
                        member->pushPacket(new CMessageStandardPacket(PChar->GetMLevel(), 0, 0, 0, message));
                        member->StatusEffectContainer->AddStatusEffect(new CStatusEffect(
                            EFFECT_LEVEL_SYNC,
                            EFFECT_LEVEL_SYNC,
                            PChar->GetMLevel(),
                            0,
                            0), true);
                        member->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE | EFFECTFLAG_ON_ZONE);
                        member->loc.zone->PushPacket(member, CHAR_INRANGE, new CCharSyncPacket(member));
                    }
                }
                Sql_Query(SqlHandle, "UPDATE accounts_parties SET partyflag = partyflag & ~%d WHERE partyid = %u AND partyflag & %d", PARTY_SYNC, m_PartyID, PARTY_SYNC);
                Sql_Query(SqlHandle, "UPDATE accounts_parties SET partyflag = partyflag | %d WHERE partyid = %u AND charid = '%u';", PARTY_SYNC, m_PartyID, PChar->id);
            }
        }
        else
        {
            if (m_PSyncTarget != nullptr)
            {
                //disable level sync
                for (uint8 i = 0; i < members.size(); ++i)
                {
                    if (members.at(i)->objtype != TYPE_PC) continue;

                    CCharEntity* member = (CCharEntity*)members.at(i);

                    if (member->status != STATUS_DISAPPEAR)
                    {
                        CStatusEffect* sync = member->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC);
                        if (sync && sync->GetDuration() == 0)
                        {
                            member->pushPacket(new CMessageBasicPacket(member, member, 10, 30, message));
                            sync->SetStartTime(server_clock::now());
                            sync->SetDuration(30000);
                        }
                    }
                }
            }
            m_PSyncTarget = nullptr;
            Sql_Query(SqlHandle, "UPDATE accounts_parties SET partyflag = partyflag & ~%d WHERE partyid = %u AND partyflag & %d", PARTY_SYNC, m_PartyID, PARTY_SYNC);
        }
    }
}
Exemple #16
0
/************************************************************************
*                                                                       *
*  Creates up to many attacks for a particular hand.			        *
*                                                                       *
************************************************************************/
void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction)
{
    uint8 num = 1;

    // Checking the players weapon hit count
    if (PWeapon->getReqLvl() <= m_attacker->GetMLevel())
    {
        num = PWeapon->getHitCount();
    }

    AddAttackSwing(ATTACK_NORMAL, direction, num);

    // Checking the players triple, double and quadruple attack
    int16 tripleAttack = m_attacker->getMod(MOD_TRIPLE_ATTACK);
    int16 doubleAttack = m_attacker->getMod(MOD_DOUBLE_ATTACK);
    int16 quadAttack = m_attacker->getMod(MOD_QUAD_ATTACK);

    //check for merit upgrades
    if (m_attacker->objtype == TYPE_PC)
    {
        CCharEntity* PChar = (CCharEntity*)m_attacker;

        //merit chance only applies if player has the job trait
        if (charutils::hasTrait(PChar, TRAIT_TRIPLE_ATTACK)) tripleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_TRIPLE_ATTACK_RATE, PChar);
        if (charutils::hasTrait(PChar, TRAIT_DOUBLE_ATTACK)) doubleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_DOUBLE_ATTACK_RATE, PChar);
        // TODO: Quadruple attack merits when SE release them.
    }

    quadAttack = dsp_cap(quadAttack,0,100);
    doubleAttack = dsp_cap(doubleAttack,0,100);
    tripleAttack = dsp_cap(tripleAttack,0,100);

    // Checking Mikage Effect - Hits Vary With Num of Utsusemi Shadows for Main Weapon
    if (m_attacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIKAGE) && m_attacker->m_Weapons[SLOT_MAIN]->getID() == PWeapon->getID())
    {
        int16 shadows = m_attacker->getMod(MOD_UTSUSEMI);
        //ShowDebug(CL_CYAN"Create Attacks: Mikage Active, Rolling Attack Chance for %d Shadowss...\n" CL_RESET, shadows);
        AddAttackSwing(ATTACK_NORMAL, direction, shadows);
    }
    else if (num == 1 && dsprand::GetRandomNumber(100) < quadAttack)
        AddAttackSwing(QUAD_ATTACK, direction, 3);
    
    else if (num == 1 && dsprand::GetRandomNumber(100) < tripleAttack)
        AddAttackSwing(TRIPLE_ATTACK, direction, 2);
    
    else if (num == 1 && dsprand::GetRandomNumber(100) < doubleAttack)
        AddAttackSwing(DOUBLE_ATTACK, direction, 1);

    // Ammo extra swing - players only
    if (m_attacker->objtype == TYPE_PC && m_attacker->getMod(MOD_AMMO_SWING) > 0)
    {
        // Check for ammo
        CCharEntity* PChar = (CCharEntity*)m_attacker;
        CItemArmor* PAmmo = PChar->getEquip(SLOT_AMMO);
        uint8 slot = PChar->equip[SLOT_AMMO];
        uint8 loc = PChar->equipLoc[SLOT_AMMO];
        if (dsprand::GetRandomNumber(100) < m_attacker->getMod(MOD_AMMO_SWING))
        {
            // Add swing, then subtract an ammo item, unequip if there's one left.
            AddAttackSwing(ATTACK_NORMAL, direction, 1);
            if (PAmmo->getQuantity() == 1)
            {
                charutils::UnequipItem(PChar, SLOT_AMMO);
                charutils::SaveCharEquip(PChar);
            }
            charutils::UpdateItem(PChar, loc, slot, -1);
            PChar->pushPacket(new CInventoryFinishPacket());
        }
    }

    // TODO: Possible Lua function for the nitty gritty stuff below.

    // Iga mod: Extra attack chance whilst dual wield is on.
    if (direction == LEFTATTACK && dsprand::GetRandomNumber(100) < m_attacker->getMod(MOD_EXTRA_DUAL_WIELD_ATTACK))
        AddAttackSwing(ATTACK_NORMAL, RIGHTATTACK, 1);

}
Exemple #17
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;
	}
}
Exemple #18
0
void CZoneEntities::DecreaseZoneCounter(CCharEntity* PChar)
{
	DSP_DEBUG_BREAK_IF(PChar == NULL);
	DSP_DEBUG_BREAK_IF(PChar->loc.zone != m_zone);

	//remove pets
	if (PChar->PPet != NULL)
	{
		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 nulled by DespawnPet
		if (PChar->PPet != NULL) {
			PChar->PPet->PBattleAI->SetCurrentAction(ACTION_NONE);
			DeletePET(PChar->PPet);//remove the TID for this pet

			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 = NULL;
		}
	}

	//remove bcnm status
	if (m_zone->m_BattlefieldHandler != NULL && 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 != NULL){
				PChar->loc.p.x = pos[0];
				PChar->loc.p.y = pos[1];
				PChar->loc.p.z = pos[2];
				PChar->loc.p.rotation = pos[3];
				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 != NULL && 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];
				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 (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it)
	{
		CMobEntity* PCurrentMob = (CMobEntity*)it->second;
		PCurrentMob->PEnmityContainer->Clear(PChar->id);
		if (PCurrentMob->m_OwnerID.id == PChar->id){
			PCurrentMob->m_OwnerID.clean();
		}
	}

	// 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());
}
bool CStatusEffectContainer::AddStatusEffect(CStatusEffect* PStatusEffect, bool silent)
{
    if(PStatusEffect == nullptr){
        ShowWarning("status_effect_container::AddStatusEffect Status effect given was nullptr!\n");
        return false;
    }

    uint16 statusId = PStatusEffect->GetStatusID();

    if(statusId >= MAX_EFFECTID){
        ShowWarning("status_effect_container::AddStatusEffect statusId given is OVER limit %d\n", statusId);
        return false;
    }

	if(CanGainStatusEffect((EFFECT)statusId, PStatusEffect->GetPower()))
	{

            // check for minimum duration
            if(PStatusEffect->GetDuration() < effects::EffectsParams[statusId].MinDuration){
                PStatusEffect->SetDuration(effects::EffectsParams[statusId].MinDuration);
            }

        // remove clean up other effects
        OverwriteStatusEffect(PStatusEffect);

        PStatusEffect->SetOwner(m_POwner);

        SetEffectParams(PStatusEffect);

        // remove effects with same type
        DelStatusEffectsByType(PStatusEffect->GetType());

        PStatusEffect->SetStartTime(gettick());

        m_StatusEffectList.push_back(PStatusEffect);

        luautils::OnEffectGain(m_POwner, PStatusEffect);

        m_POwner->addModifiers(&PStatusEffect->modList);

        if (PStatusEffect->GetStatusID() >= EFFECT_FIRE_MANEUVER &&
            PStatusEffect->GetStatusID() <= EFFECT_DARK_MANEUVER &&
            m_POwner->objtype == TYPE_PC)
        {
            puppetutils::CheckAttachmentsForManeuver((CCharEntity*)m_POwner, PStatusEffect->GetStatusID(), true);
        }

        if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in
        {
            m_POwner->UpdateHealth();
        }

        if (m_POwner->objtype == TYPE_PC)
        {
            CCharEntity* PChar = (CCharEntity*)m_POwner;

            if (PStatusEffect->GetIcon() != 0)
            {
                UpdateStatusIcons();
            }

			if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in
			{
				//check for latents
				PChar->PLatentEffectContainer->CheckLatentsFoodEffect();
				PChar->PLatentEffectContainer->CheckLatentsStatusEffect();
                PChar->PLatentEffectContainer->CheckLatentsRollSong(PStatusEffect->GetFlag() & (EFFECTFLAG_SONG | EFFECTFLAG_ROLL));
				PChar->UpdateHealth();

				PChar->pushPacket(new CCharHealthPacket(PChar));
			}
            PChar->pushPacket(new CCharSyncPacket(PChar));
        }
        m_POwner->updatemask |= UPDATE_HP;

        return true;
	}

    return false;
}
Exemple #20
0
void CZoneEntities::PushPacket(CBaseEntity* PEntity, GLOBAL_MESSAGE_TYPE message_type, CBasicPacket* packet)
{
	// Do not send packets that are updates of a hidden GM..
	if (packet != NULL && packet->getType() == 0x0D && PEntity != NULL && PEntity->objtype == TYPE_PC && ((CCharEntity*)PEntity)->m_isGMHidden)
	{
		// Ensure this packet is not despawning us..
		if (packet->getData()[0x06] != 0x20)
		{
			delete packet;
			return;
		}
	}

	if (!m_charList.empty())
	{
		switch (message_type)
		{
			case CHAR_INRANGE_SELF:
			{
				if (PEntity->objtype == TYPE_PC)
				{
					((CCharEntity*)PEntity)->pushPacket(new CBasicPacket(*packet));
				}
			}
			case CHAR_INRANGE:
			{
				for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
				{
					CCharEntity* PCurrentChar = (CCharEntity*)it->second;
					if (PEntity != PCurrentChar)
					{
						if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 50)
						{
							if (packet != NULL && packet->getType() == 0x0E &&
								(RBUFB(packet->getData(), (0x0A) - 4) != 0x20 ||
								RBUFB(packet->getData(), (0x0A) - 4) != 0x0F))
							{
								uint32 id = RBUFL(packet->getData(), (0x04) - 4);
								uint16 targid = RBUFW(packet->getData(), (0x08) - 4);

								CBaseEntity* entity = GetEntity(targid);

								SpawnIDList_t spawnlist;

								if (entity)
								{
									if (entity->targid < 0x400)
									{
										if (entity->objtype == TYPE_MOB)
										{
											spawnlist = PCurrentChar->SpawnMOBList;
										}
										else if (entity->objtype == TYPE_NPC)
										{
											spawnlist = PCurrentChar->SpawnNPCList;
										}
									}
									else if (entity->targid >= 0x700)
									{
										spawnlist = PCurrentChar->SpawnPETList;
									}
									else
									{
										entity = NULL;
									}
								}
								if (!entity)
								{
									// got a char or nothing as the target of this entity update (which really shouldn't happen ever)
									// so we're just going to skip this packet
									break;
								}
								SpawnIDList_t::iterator iter = spawnlist.lower_bound(id);

								if (!(iter == spawnlist.end() ||
									spawnlist.key_comp()(id, iter->first)))
								{
									PCurrentChar->pushPacket(new CBasicPacket(*packet));
								}
							}
							else
							{
								PCurrentChar->pushPacket(new CBasicPacket(*packet));
							}
						}
					}
				}
			}
			break;
			case CHAR_INSHOUT:
			{
				for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
				{
					CCharEntity* PCurrentChar = (CCharEntity*)it->second;
					if (PEntity != PCurrentChar)
					{
						if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 180)
						{
							PCurrentChar->pushPacket(new CBasicPacket(*packet));
						}
					}
				}
			}
			break;
			case CHAR_INZONE:
			{
				for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it)
				{
					CCharEntity* PCurrentChar = (CCharEntity*)it->second;
					if (PEntity != PCurrentChar)
					{
						PCurrentChar->pushPacket(new CBasicPacket(*packet));
					}
				}
			}
			break;
		}
	}
	delete packet;
}
Exemple #21
0
void CParty::DelMember(CBattleEntity* PEntity)
{
	DSP_DEBUG_BREAK_IF(PEntity == NULL);
	DSP_DEBUG_BREAK_IF(PEntity->PParty != this);

	if (m_PLeader == PEntity)
	{
		RemovePartyLeader(PEntity);
	}
	else
	{
		for (uint32 i = 0; i < members.size(); ++i)
		{
			if (PEntity == members.at(i))
			{
				members.erase(members.begin() + i);

				if (m_PartyType == PARTY_PCS)
				{
					CCharEntity* PChar = (CCharEntity*)PEntity;

					if (m_PQuaterMaster == PChar)
					{
						SetQuaterMaster(NULL);
					}
					if (m_PSyncTarget == PChar)
					{
						SetSyncTarget(NULL, 553);
						CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC);
						if (sync && sync->GetDuration() == 0)
						{
							PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553));
							sync->SetStartTime(gettick());
							sync->SetDuration(30000);
						}
						DisableSync();
					}
					if (m_PSyncTarget != NULL && m_PSyncTarget != PChar)
					{
						if (PChar->status != STATUS_DISAPPEAR &&
							PChar->getZone() == m_PSyncTarget->getZone())
						{
							CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC);
							if (sync && sync->GetDuration() == 0)
							{
								PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553));
								sync->SetStartTime(gettick());
								sync->SetDuration(30000);
							}
						}
					}
					PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size());

					PChar->pushPacket(new CPartyDefinePacket(NULL));
					PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, PChar->getZone()));
					PChar->pushPacket(new CCharUpdatePacket(PChar));
					PChar->PParty = NULL;

					if (PChar->PTreasurePool != NULL &&
						PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE)
					{
						PChar->PTreasurePool->DelMember(PChar);
						PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO);
						PChar->PTreasurePool->AddMember(PChar);
						PChar->PTreasurePool->UpdatePool(PChar);
					}
				}
				break;
			}
		}
	}
}
Exemple #22
0
void CMobEntity::DropItems()
{
    CCharEntity* PChar = (CCharEntity*)GetEntity(m_OwnerID.targid, TYPE_PC);

    if (PChar != nullptr && PChar->id == m_OwnerID.id)
    {

        loc.zone->PushPacket(this, CHAR_INRANGE, new CMessageBasicPacket(PChar, this, 0, 0, MSGBASIC_DEFEATS_TARG));

        if (!CalledForHelp())
        {
            blueutils::TryLearningSpells(PChar, this);
            m_UsedSkillIds.clear();

            if (m_giveExp)
            {
                charutils::DistributeExperiencePoints(PChar, this);
            }

            DropList_t* DropList = itemutils::GetDropList(m_DropID);
            //ShowDebug(CL_CYAN"DropID: %u dropping with TH Level: %u\n" CL_RESET, PMob->m_DropID, PMob->m_THLvl);

            if (DropList != nullptr && !getMobMod(MOBMOD_NO_DROPS) && DropList->size())
            {
                for (uint8 i = 0; i < DropList->size(); ++i)
                {
                    //THLvl is the number of 'extra chances' at an item. If the item is obtained, then break out.
                    uint8 tries = 0;
                    uint8 maxTries = 1 + (m_THLvl > 2 ? 2 : m_THLvl);
                    uint8 bonus = (m_THLvl > 2 ? (m_THLvl - 2) * 10 : 0);
                    while (tries < maxTries)
                    {
                        if (dsprand::GetRandomNumber(1000) < DropList->at(i).DropRate * map_config.drop_rate_multiplier + bonus)
                        {
                            PChar->PTreasurePool->AddItem(DropList->at(i).ItemID, this);
                            break;
                        }
                        tries++;
                    }
                }
            }

            // check for gil (beastmen drop gil, some NMs drop gil)
            if (CanDropGil() || (map_config.all_mobs_gil_bonus > 0 && getMobMod(MOBMOD_GIL_MAX) >= 0)) // Negative value of MOBMOD_GIL_MAX is used to prevent gil drops in Dynamis/Limbus.
            {
                charutils::DistributeGil(PChar, this); // TODO: REALISATION MUST BE IN TREASUREPOOL
            }
            //check for seal drops
            /* MobLvl >= 1 = Beastmen Seals ID=1126
                      >= 50 = Kindred Seals ID=1127
                      >= 75 = Kindred Crests ID=2955
                      >= 90 = High Kindred Crests ID=2956
            */

            uint16 Pzone = PChar->getZone();

            bool validZone = ((Pzone > 0 && Pzone < 39) || (Pzone > 42 && Pzone < 134) || (Pzone > 135 && Pzone < 185) || (Pzone > 188 && Pzone < 255));

            if (validZone && charutils::GetRealExp(PChar->GetMLevel(), GetMLevel()) > 0)
            {
                if (((PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET) && conquest::GetInfluenceGraphics(PChar->loc.zone->GetRegionID()) < 64) ||
                    (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SANCTION) && PChar->loc.zone->GetRegionID() >= 28 && PChar->loc.zone->GetRegionID() <= 32) ||
                    (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_SIGIL) && PChar->loc.zone->GetRegionID() >= 33 && PChar->loc.zone->GetRegionID() <= 40)) &&
                    m_Element > 0 && dsprand::GetRandomNumber(100) < 20) // Need to move to CRYSTAL_CHANCE constant
                {
                    PChar->PTreasurePool->AddItem(4095 + m_Element, this);
                }

                // Todo: Avatarite and Geode drops during day/weather. Much higher chance during weather than day.
                // Item element matches day/weather element, not mob crystal. Lv80+ xp mobs can drop Avatarite.
                // Wiki's have conflicting info on mob lv required for Geodes. One says 50 the other 75. I think 50 is correct.

                if (dsprand::GetRandomNumber(100) < 20 && PChar->PTreasurePool->CanAddSeal() && !getMobMod(MOBMOD_NO_DROPS))
                {
                    //RULES: Only 1 kind may drop per mob
                    if (GetMLevel() >= 75 && luautils::IsExpansionEnabled("ABYSSEA")) //all 4 types
                    {
                        switch (dsprand::GetRandomNumber(4))
                        {
                            case 0:
                                PChar->PTreasurePool->AddItem(1126, this);
                                break;
                            case 1:
                                PChar->PTreasurePool->AddItem(1127, this);
                                break;
                            case 2:
                                //PChar->PTreasurePool->AddItem(2955, this);
                                break;
                            case 3:
                                //PChar->PTreasurePool->AddItem(2956, this);
                                break;
                        }
                    }
                    else if (GetMLevel() >= 70 && luautils::IsExpansionEnabled("ABYSSEA")) //b.seal & k.seal & k.crest
                    {
                        switch (dsprand::GetRandomNumber(3))
                        {
                            case 0:
                                PChar->PTreasurePool->AddItem(1126, this);
                                break;
                            case 1:
                                PChar->PTreasurePool->AddItem(1127, this);
                                break;
                            case 2:
                                //PChar->PTreasurePool->AddItem(2955, this);
                                break;
                        }
                    }
                    else if (GetMLevel() >= 50) //b.seal & k.seal only
                    {
                        if (dsprand::GetRandomNumber(2) == 0)
                        {
                            PChar->PTreasurePool->AddItem(1126, this);
                        }
                        else
                        {
                            PChar->PTreasurePool->AddItem(1127, this);
                        }
                    }
                    else
                    {
                        //b.seal only
                        PChar->PTreasurePool->AddItem(1126, this);
                    }
                }
            }
        }

        PChar->setWeaponSkillKill(false);
        StatusEffectContainer->KillAllStatusEffect();

        // NOTE: this is called for all alliance / party members!
        luautils::OnMobDeath(this, PChar);

    }
    else
    {
        luautils::OnMobDeath(this, nullptr);
    }
}