Example #1
0
void Spawn2::LoadGrid() {
	if(!npcthis)
		return;
	if(grid_ < 1)
		return;
	if(!entity_list.IsMobInZone(npcthis))
		return;
	//dont set an NPC's grid until its loaded for them.
	npcthis->SetGrid(grid_);
	npcthis->AssignWaypoints(grid_);
	_log(SPAWNS__MAIN, "Spawn2 %d: Loading grid %d for %s", spawn2_id, grid_, npcthis->GetName());
}
Example #2
0
int
main ( int argc,
       char *argv[] )
{
  int i;

  for ( i=1; i<argc; ++i )
    {
      Graph *g = new Graph ( );
      EntityList *el = new EntityList ( );

      el->parseFromFile ( argv[i] );
      g->initFromEntityList ( el );
      delete el;

      g->assignGridCoordinates ( );
      delete g;
    }

  return 0;
}
Example #3
0
void ScrollComponent::SetPosition(CL_Vec2f vDisplacement, bool bForceUpdate)
{
	if (vDisplacement == CL_Vec2f(0,0) && !bForceUpdate) return;
	
	/*
	//this works, but it still totally feels wrong, really I would need to turn "momentum" off as well, and perfectly tune the
	//sensitivity so it feels like you're dragging the scroll bar

	if (IsDesktop())
	{
		vDisplacement.y *= -1; //on desktops where you use a mouse, it makes more sense to drag the scroll bar down, rather than "drag the screen up"
	}
	*/

	m_vecChildPos += vDisplacement;

	//force it within our ranges
	ForceRange(m_vecChildPos.x, m_pBoundsRect->left, m_pBoundsRect->right);
	if (m_pBoundsRect->top > m_pBoundsRect->bottom) m_pBoundsRect->top = m_pBoundsRect->bottom;
	ForceRange(m_vecChildPos.y, m_pBoundsRect->top, m_pBoundsRect->bottom);
	
	CL_Vec2f percent2d(0,0);
	//avoid divide by 0 errors
	if (m_pBoundsRect->get_width() != 0) percent2d.x = m_vecChildPos.x/(-m_pBoundsRect->get_width());
	if (m_pBoundsRect->get_height() != 0) percent2d.y = m_vecChildPos.y/ (-m_pBoundsRect->get_height());

	m_progressVar->Set(percent2d);
	
	//also run this on all children
	EntityList *pChildren = GetParent()->GetChildren();

	Variant *pPos;
	EntityList::iterator itor = pChildren->begin();
	while (itor != pChildren->end())
	{
		pPos = (*itor)->GetVar("pos2d");
		pPos->Set(m_vecChildPos);
		itor++;
	}
}
Example #4
0
uint32 SpawnGroup::GetNPCType() {
	int npcType = 0;
	int totalchance = 0;

	if(!entity_list.LimitCheckGroup(id, group_spawn_limit))
		return(0);

	std::list<SpawnEntry*>::iterator cur,end;
	std::list<SpawnEntry*> possible;
	cur = list_.begin();
	end = list_.end();
	for(; cur != end; ++cur) {
		SpawnEntry *se = *cur;

		if(!entity_list.LimitCheckType(se->NPCType, se->npc_spawn_limit))
			continue;

		totalchance += se->chance;
		possible.push_back(se);
	}
	if(totalchance == 0)
		return 0;


	int32 roll = 0;
	roll = MakeRandomInt(0, totalchance-1);

	cur = possible.begin();
	end = possible.end();
	for(; cur != end; ++cur) {
		SpawnEntry *se = *cur;
		if (roll < se->chance) {
			npcType = se->NPCType;
			break;
		} else {
			roll -= se->chance;
		}
	}
	return npcType;
}
Example #5
0
bool Beacon::Process()
{
	if(remove_me)
	{
		return false;
	}

	if
	(
		spell_timer.Enabled() &&
		spell_timer.Check() &&
		IsValidSpell(spell_id)
	)
	{
		Mob *caster = entity_list.GetMob(caster_id);
		if(caster && spell_iterations-- && max_targets)
		{
			// NPCs should never be affected by an AE they cast. PB AEs shouldn't affect caster either
			// I don't think any other cases that get here matter
			bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled()) && spells[spell_id].targettype != ST_AECaster;
			entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust, &max_targets);
		}
		else
		{
			// spell is done casting, or caster disappeared
			spell_id = 0xFFFF;
			spell_iterations = 0;
			spell_timer.Disable();
			caster_id = 0;
		}
	}

	if(remove_timer.Enabled() && remove_timer.Check())
	{
		return false;
	}

	return true;
}
Example #6
0
void Raid::SendRaidMoveAll(const char* who)
{
	Client *c = entity_list.GetClientByName(who);
	SendRaidRemoveAll(who);
	if(c)
		SendRaidCreate(c);
	SendMakeLeaderPacket(leadername);
	SendRaidAddAll(who);
	if(c){
		SendBulkRaid(c);
	if(IsLocked()) { SendRaidLockTo(c); }
	}
}
Example #7
0
void EntityShadows::doRun(::Camera& camera, const TileList& tl, const EntityList& el) {
	// If shadows are not enabled, return immediatly.
	if (!gfx.shadows_enable) {
		return;
	}
	// Get the renderer.
	auto& renderer = Renderer::get();
	// Do not write into the depth buffer.
	renderer.setDepthWriteEnabled(false);
	// Enable depth tests.
	renderer.setDepthTestEnabled(true);
	// Enable blending.
	renderer.setBlendingEnabled(true);
	renderer.setBlendFunction(BlendFunction::Zero, BlendFunction::OneMinusSourceColour);

	// Keep track of the number of rendered shadows.
	size_t count = 0;

	if (gfx.shadows_highQuality_enable) {
		// Render high-quality shadows.
		for (size_t i = 0; i < el.getSize(); ++i) {
			CHR_REF ichr = el.get(i).ichr;
			if (INVALID_CHR_REF == ichr) continue;
			if (0 == _currentModule->getObjectHandler().get(ichr)->shadow_size) continue;
			doHighQualityShadow(ichr);
			count++;
		}
	} else {
		// Render low-quality shadows.
		for (size_t i = 0; i < el.getSize(); ++i) {
			CHR_REF ichr = el.get(i).ichr;
			if (INVALID_CHR_REF == ichr) continue;
			if (0 == _currentModule->getObjectHandler().get(ichr)->shadow_size) continue;
			doLowQualityShadow(ichr);
			count++;
		}
	}
}
  void _shutdown()
  {
    if( mTerrainPaging )
    {
      OGRE_DELETE mTerrainPaging;
      OGRE_DELETE mPageManager;
    }
    else
      OGRE_DELETE mTerrainGroup;

    OGRE_DELETE mTerrainGlobals;
    mHouseList.clear();
    SdkSample::_shutdown();
  }
Example #9
0
void Object::RandomSpawn(bool send_packet) {
	if(!m_ground_spawn)
		return;
	
	m_data.x = MakeRandomFloat(m_min_x, m_max_x);
	m_data.y = MakeRandomFloat(m_min_y, m_max_y);
	respawn_timer.Disable();
	
	if(send_packet) {
		EQApplicationPacket app;
		CreateSpawnPacket(&app);
		entity_list.QueueClients(NULL, &app, true);
	}
}
Example #10
0
bool Beacon::Process()
{
	if(remove_me)
	{
		return false;
	}

	if
	(
		spell_timer.Enabled() &&
		spell_timer.Check() &&
		IsValidSpell(spell_id)
	)
	{
		Mob *caster = entity_list.GetMob(caster_id);
		if(caster && spell_iterations--)
		{
			bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled());	//NPC AE spells do not affect the NPC caster
			entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust);
		}
		else
		{
			// spell is done casting, or caster disappeared
			spell_id = 0xFFFF;
			spell_iterations = 0;
			spell_timer.Disable();
			caster_id = 0;
		}
	}

	if(remove_timer.Enabled() && remove_timer.Check())
	{
		return false;
	}

	return true;
}
Example #11
0
void Map::ResolveCell(EntityList& entities, 
    Entities::EntityDispatcherBase& dispatcher)
{
    assert(entities.count());

    Location loc = entities[0]->NewLocation();

    QList<Entity*> new_entities;

    for (EntityList::const_iterator it = entities.begin(); 
         it != entities.end(); ++it)
    {
        Entity* lhs = *it;
        
        for (EntityList::const_iterator jt = it + 1; jt != entities.end(); jt++)
        {
            if (!lhs->Alive())
            {
                break;
            }

            Entity* rhs = *jt;

            if (!rhs->Alive())
            {
                continue;
            }

            new_entities.append(dispatcher.Dispatch(*lhs, *rhs));
        }
    }

    for (EntityList::const_iterator it = entities.begin(); 
         it != entities.end(); ++it)
    {
        Entity *entity_p( *it );
        if (entity_p->Alive())
        {
            entity_p->SetLocation(loc);
            entity_p->Commit();
        }
    }

    for (QList<Entity*>::const_iterator it = new_entities.begin(); 
         it != new_entities.end(); ++it)
    {
        Entity *entity_p = *it;
        entity_p->SetLocation(loc);
        entity_p->Commit();
        entities.append(entity_p);
    }
}
Example #12
0
void Group::DisbandGroup() {
	EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct));

	GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer;
	gu->action = groupActDisband;

	Client *Leader = nullptr;

	uint32 i;
	for (i = 0; i < MAX_GROUP_MEMBERS; i++)
	{
		if (members[i] == nullptr)
		{
			continue;
		}

		if (members[i]->IsClient())
		{
			if(IsLeader(members[i]))
			{
				Leader = members[i]->CastToClient();
			}

			strcpy(gu->yourname, members[i]->GetName());
			database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID());
			members[i]->CastToClient()->QueuePacket(outapp);
		}
		
		members[i]->SetGrouped(false);
		members[i] = nullptr;
		membername[i][0] = '\0';
	}

	ServerPacket* pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct));
	ServerDisbandGroup_Struct* dg = (ServerDisbandGroup_Struct*)pack->pBuffer;
	dg->zoneid = zone->GetZoneID();
	dg->groupid = GetID();
	dg->instance_id = zone->GetInstanceID();
	worldserver.SendPacket(pack);
	safe_delete(pack);

	entity_list.RemoveGroup(GetID());
	if(GetID() != 0)
	{
		database.ClearGroup(GetID());
	}

	safe_delete(outapp);
}
Example #13
0
void Raid::SetGroupMentor(uint32 group_id, int percent, char *name)
{
	if (group_id > 11)
		return;
	group_mentor[group_id].name = name;
	group_mentor[group_id].mentor_percent = percent;
	Client *client = entity_list.GetClientByName(name);
	group_mentor[group_id].mentoree = client ? client : nullptr;

	std::string query = StringFormat("UPDATE raid_leaders SET mentoree = '%s', mentor_percent = %i WHERE gid = %i AND rid = %i LIMIT 1",
			name, percent, group_id, GetID());
	auto results = database.QueryDatabase(query);
	if (!results.Success())
		LogFile->write(EQEMuLog::Error, "Unable to set raid group mentor: %s\n", results.ErrorMessage().c_str());
}
Example #14
0
bool CheckSpawnLimit(int32 in_NPCTypeID)
{
	if ( in_NPCTypeID <= 0 )
		return false;

	// check limit from database
	int db_limit = Database::Instance()->CheckNPCTypeSpawnLimit(in_NPCTypeID);
	if (db_limit > 0) // Doing this check first because we want to avoid a zone entity_list iteration if we can help it
	{
		// There should be a limit now, let's check to see how many exist in the zone
		if ( entity_list.GetNPCTypeCount(in_NPCTypeID) >= db_limit )
			return false; // Hit the cap, don't allow any more to spawn!
	}
	return true;
}
Example #15
0
void NetConnection::ListenNewClients()
{

	uchar		buffer[1024];

	int			status;
	unsigned short	port;

	struct sockaddr_in	from;
	struct in_addr	in;
	unsigned int	fromlen;

	from.sin_family = AF_INET;
	fromlen = sizeof(from);

#ifdef WIN32
	status = recvfrom(listening_socket, (char *) &buffer, sizeof(buffer), 0,(struct sockaddr*) &from, (int *) &fromlen);
#else
	status = recvfrom(listening_socket, &buffer, sizeof(buffer), 0,(struct sockaddr*) &from, &fromlen);
#endif


	if (status > 1)
	{
		Client* client = 0;

		port = from.sin_port;
		in.s_addr = from.sin_addr.s_addr;

		//cout << Timer::GetCurrentTime() << " Data from ip: " << inet_ntoa(in) << " port:" << ntohs(port) << " length: " << status << endl;
		if (!client_list.RecvData(in.s_addr, from.sin_port, buffer, status)) {
			// If it is a new client make sure it has the starting flag set. Ignore otherwise
			if (buffer[0] & 0x20)
			{
				EQC::Common::PrintF(CP_CLIENT, "New client from %s:%i\n", inet_ntoa(in), ntohs(port));
				client = new Client(in.s_addr, port, listening_socket);
				client->ReceiveData(buffer, status);
				entity_list.AddClient(client);
				client_list.Add(client);
				numclients++;
			}
			else
			{
				return;
			}
		}
	}
}
Example #16
0
void DebrisFountain::projectDebris(EntityList &entityList, Direction direction, Position from, double spread, int amount, RGB &colour, float size)
{
	double startAngle = direction.Angle() - spread / 2.0;

	double angleStep = spread / (double) amount;
	for (int i = 0; i < amount; i++)
	{
		Direction debrisDirection{direction.Speed(), startAngle+angleStep*i, ((rand() % 10) / 10.f) - 0.5f};
		
		Actor *actor = new Actor(colour, mover, renderer, std::unique_ptr<ElapsedTimeToLive>(new ElapsedTimeToLive(1000)));
		actor->position().set(from.X(), from.Y(), from.Rotation());
		actor->direction().set(debrisDirection);
		actor->shape().Radius(size);

		entityList.add(actor);
	}
}
Example #17
0
bool Doors::Process()
{
	if (close_timer.Enabled() && close_timer.Check() && IsDoorOpen()) {
		if (open_type == 40 || GetTriggerType() == 1) {
			auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
			MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer;
			md->doorid = door_id;
			md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
			entity_list.QueueClients(0, outapp);
			safe_delete(outapp);
		}

		triggered = false;
		close_timer.Disable();
		SetOpenState(false);
	}
	return true;
}
Example #18
0
void QuestManager::signalwith(int npc_id, int signal_id, int wait_ms) {
// SCORPIOUS2K - signal command
	// signal(npcid) - generates EVENT_SIGNAL on specified npc
	if(wait_ms > 0) {
		STimerList.push_back(SignalTimer(wait_ms, npc_id, signal_id));
		return;
	}

	if (npc_id<1)
	{
		printf("signal() bad npcid=%i\n",npc_id);
	}
	else
	{
		//initiator* signalnpc=0;
		entity_list.SignalMobsByNPCID(npc_id, signal_id);
	}
}
Example #19
0
bool Object::Process(){
	if(m_type == OT_DROPPEDITEM && decay_timer.Enabled() && decay_timer.Check()) {
		// Send click to all clients (removes entity on client)
		EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
		ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer;
		click_object->drop_id = GetID();
		entity_list.QueueClients(NULL, outapp, false);
		safe_delete(outapp);

		// Remove object
		database.DeleteObject(m_id);
		return false;
	}
	
	if(m_ground_spawn && respawn_timer.Check()){
		RandomSpawn(true);
	}
	return true;
}
Example #20
0
void QuestManager::rain(int weather) {
	zone->zone_weather = (WeatherTypesEnum)(weather);

	APPLAYER* outapp = new APPLAYER(OP_Weather, 8);
	memset(outapp->pBuffer, 0, 8);

	if (zone->zone_weather == 1)
	{
		outapp->pBuffer[6] = 0x31; // Rain
	}
	if (zone->zone_weather == 2)
	{
		outapp->pBuffer[0] = 0x01;
		outapp->pBuffer[4] = 0x02; 
	}
					
	entity_list.QueueClients(initiator,outapp);
	safe_delete(outapp);//delete outapp;
}
Example #21
0
void Raid::SendRaidMove(const char* who, Client *to)
{
	if(!to)
		return;

	Client *c = entity_list.GetClientByName(who);
	if(c && c == to){
		SendRaidCreate(c);
		SendMakeLeaderPacketTo(leadername, c);
	}
	SendRaidRemove(who, to);
	SendRaidAdd(who, to);
	if(c && c == to){
		SendBulkRaid(c);
		if(IsLocked()) {
			SendRaidLockTo(c);
		}
	}
}
Example #22
0
void Group::VerifyGroup() {
	/*
		The purpose of this method is to make sure that a group
		is in a valid state, to prevent dangling pointers.
		Only called every once in a while (on member re-join for now).
	*/

	uint32 i;
	for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
		if (membername[i][0] == '\0') {
#if EQDEBUG >= 7
LogFile->write(EQEMuLog::Debug, "Group %lu: Verify %d: Empty.\n", (unsigned long)GetID(), i);
#endif
			members[i] = nullptr;
			continue;
		}

		//it should be safe to use GetClientByName, but Group is trying
		//to be generic, so we'll go for general Mob
		Mob *them = entity_list.GetMob(membername[i]);
		if(them == nullptr && members[i] != nullptr) {	//they arnt here anymore....
#if EQDEBUG >= 6
		LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' has disappeared!!", (unsigned long)GetID(), membername[i]);
#endif
			membername[i][0] = '\0';
			members[i] = nullptr;
			continue;
		}

		if(them != nullptr && members[i] != them) {	//our pointer is out of date... not so good.
#if EQDEBUG >= 5
		LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' had an out of date pointer!!", (unsigned long)GetID(), membername[i]);
#endif
			members[i] = them;
			continue;
		}
#if EQDEBUG >= 8
		LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' is valid.", (unsigned long)GetID(), membername[i]);
#endif
	}
}
Example #23
0
void Raid::SetRaidLeader(const char *wasLead, const char *name)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
	char* query = 0;
	MYSQL_RES *result;
	if (!database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET israidleader=0 WHERE name='%s'", wasLead),errbuf,&result)){
		printf("Set Raid Leader error: %s\n", errbuf);
	}
	else
		mysql_free_result(result);

	safe_delete_array(query);
	query = 0;

	if (!database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET israidleader=1 WHERE name='%s'", name),errbuf,&result)){
		printf("Set Raid Leader error: %s\n", errbuf);
	}
	else
		mysql_free_result(result);

	safe_delete_array(query);

	strn0cpy(leadername, name, 64);

	Client *c = entity_list.GetClientByName(name);
	if(c)
		SetLeader(c);

	LearnMembers();
	VerifyRaid();
	SendMakeLeaderPacket(name);

	ServerPacket *pack = new ServerPacket(ServerOP_RaidLeader, sizeof(ServerRaidGeneralAction_Struct));
	ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
	rga->rid = GetID();
	strn0cpy(rga->playername, name, 64);
	rga->zoneid = zone->GetZoneID();
	rga->instance_id = zone->GetInstanceID();
	worldserver.SendPacket(pack);
	safe_delete(pack);
}
Example #24
0
void Doors::ToggleState(Mob *sender)
{
	if(GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || opentype == 58 || opentype == 40) { // borrowed some NPCOpen criteria
		return;
	}

	EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
	MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
	md->doorid = door_id;

	if(!isopen) {
		md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
		isopen=true;
	}
	else
	{
		md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
		isopen=false;
	}

	entity_list.QueueClients(sender,outapp,false);
	safe_delete(outapp);
}
Example #25
0
void Doors::ForceClose(Mob *sender, bool alt_mode) {
	auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
	MoveDoor_Struct *move_door_packet;
	move_door_packet = (MoveDoor_Struct *) outapp->pBuffer;
	move_door_packet->doorid = door_id;
	move_door_packet->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; // change from original (open to close)
	entity_list.QueueClients(sender, outapp, false);
	safe_delete(outapp);

	if (!alt_mode) { // original function
		if (!is_open) {
			if (!disable_timer)
				close_timer.Start();
			is_open = true;
		} else {
			close_timer.Disable();
			is_open = false;
		}
	} else { // alternative function
		if (is_open)
			close_timer.Trigger();
	}
}
Example #26
0
void Doors::ForceOpen(Mob *sender, bool alt_mode)
{
	EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
	MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
	md->doorid = door_id;
	md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
	entity_list.QueueClients(sender,outapp,false);
	safe_delete(outapp);

	if(!alt_mode) { // original function
		if(!isopen) {
			close_timer.Start();
			isopen=true;
		}
		else {
			close_timer.Disable();
			isopen=false;
		}
	}
	else { // alternative function
		close_timer.Start();
		isopen=true;
	}
}
Example #27
0
void Raid::VerifyRaid()
{
	for(int x = 0; x < MAX_RAID_MEMBERS; x++)
	{
		if(strlen(members[x].membername) == 0){
			members[x].member = nullptr;
		}
		else{
			Client *c = entity_list.GetClientByName(members[x].membername);
			if(c){
				members[x].member = c;
			}
			else{
				members[x].member = nullptr;
			}
		}
		if(members[x].IsRaidLeader){
			if(strlen(members[x].membername) > 0){
				SetLeader(members[x].member);
				strn0cpy(leadername, members[x].membername, 64);
			}
		}
	}
}
Example #28
0
void Raid::RemoveMember(const char *characterName)
{
	std::string query = StringFormat("DELETE FROM raid_members where name='%s'", characterName);
	auto results = database.QueryDatabase(query);

	Client *client = entity_list.GetClientByName(characterName);
	disbandCheck = true;
	SendRaidRemoveAll(characterName);
	SendRaidDisband(client);
	LearnMembers();
	VerifyRaid();

	if(client)
		client->SetRaidGrouped(false);

	ServerPacket *pack = new ServerPacket(ServerOP_RaidRemove, sizeof(ServerRaidGeneralAction_Struct));
	ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
	rga->rid = GetID();
	rga->instance_id = zone->GetInstanceID();
	strn0cpy(rga->playername, characterName, 64);
	rga->zoneid = zone->GetZoneID();
	worldserver.SendPacket(pack);
	safe_delete(pack);
}
Example #29
0
void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) {
	// Added 12/08. Started compressing loot struct on live.
	char tmp[10];
	if(player_corpse_depop) {
		SendLootReqErrorPacket(client, 0);
		return;
	}

	if(IsPlayerCorpse() && corpse_db_id == 0) {
		// SendLootReqErrorPacket(client, 0);
		client->Message(13, "Warning: Corpse's dbid = 0! Corpse will not survive zone shutdown!");
		std::cout << "Error: PlayerCorpse::MakeLootRequestPackets: dbid = 0!" << std::endl;
		// return;
	}

	if(is_locked && client->Admin() < 100) {
		SendLootReqErrorPacket(client, 0);
		client->Message(13, "Error: Corpse locked by GM.");
		return;
	}

	if(being_looted_by == 0)
		being_looted_by = 0xFFFFFFFF;

	if(this->being_looted_by != 0xFFFFFFFF) {
		// lets double check....
		Entity* looter = entity_list.GetID(this->being_looted_by);
		if(looter == 0)
			this->being_looted_by = 0xFFFFFFFF;
	}

	uint8 Loot_Request_Type = 1;
	bool loot_coin = false;
	if(database.GetVariable("LootCoin", tmp, 9))
		loot_coin = (atoi(tmp) == 1);

	if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) {
		SendLootReqErrorPacket(client, 0);
		Loot_Request_Type = 0;
	}
	else if (IsPlayerCorpse() && char_id == client->CharacterID()) {
		Loot_Request_Type = 2;
	}
	else if ((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) {
		Loot_Request_Type = 2;
	}
	else if (GetPlayerKillItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */
		Loot_Request_Type = 3;
	}
	else if (GetPlayerKillItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */
		Loot_Request_Type = 4;
	}
	else if (GetPlayerKillItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */
		Loot_Request_Type = 5;
	}

	if (Loot_Request_Type == 1) {
		if (client->Admin() < 100 || !client->GetGM()) {
			SendLootReqErrorPacket(client, 2);
		}
	}

	if(Loot_Request_Type >= 2 || (Loot_Request_Type == 1 && client->Admin() >= 100 && client->GetGM())) {
		this->being_looted_by = client->GetID();
		EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct));
		moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer;

		d->response		= 1;
		d->unknown1		= 0x42;
		d->unknown2		= 0xef;

		/* Dont take the coin off if it's a gm peeking at the corpse */
		if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) {
			if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) {
				d->copper		= 0;
				d->silver		= 0;
				d->gold			= 0;
				d->platinum		= 0;
				Group *cgroup = client->GetGroup();
				cgroup->SplitMoney(GetCopper(), GetSilver(), GetGold(), GetPlatinum(), client);
			}
			else {
				d->copper		= this->GetCopper();
				d->silver		= this->GetSilver();
				d->gold			= this->GetGold();
				d->platinum		= this->GetPlatinum();
				client->AddMoneyToPP(GetCopper(), GetSilver(), GetGold(), GetPlatinum(), false);
			}

			RemoveCash();
			Save();
		}

		auto timestamps = database.GetItemRecastTimestamps(client->CharacterID());
		outapp->priority = 6;
		client->QueuePacket(outapp);
		safe_delete(outapp);
		if(Loot_Request_Type == 5) {
			int pkitem = GetPlayerKillItem();
			const Item_Struct* item = database.GetItem(pkitem);
			ItemInst* inst = database.CreateItem(item, item->MaxCharges);
			if(inst) {
				if (item->RecastDelay)
					inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
				client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
				safe_delete(inst);
			}
			else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); }

			client->QueuePacket(app);
			return;
		}

		int i = 0;
		const Item_Struct* item = 0;
		ItemList::iterator cur,end;
		cur = itemlist.begin();
		end = itemlist.end();

		int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, client->GetClientVersion());

		for(; cur != end; ++cur) {
			ServerLootItem_Struct* item_data = *cur;
			item_data->lootslot = 0xFFFF;

			// Dont display the item if it's in a bag

			// Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
			if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || Loot_Request_Type>=3 ||
				(item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) {
				if(i < corpselootlimit) {
					item = database.GetItem(item_data->item_id);
					if(client && item) {
						ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned);
						if(inst) {
							if (item->RecastDelay)
								inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
							// MainGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = MainGeneral1 + MainCursor
							client->SendItemPacket(i + EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
							safe_delete(inst);
						}

						item_data->lootslot = i;
					}
				}

				i++;
			}
		}

		if(IsPlayerCorpse() && (char_id == client->CharacterID() || client->GetGM())) {
			if(i > corpselootlimit) {
				client->Message(15, "*** This corpse contains more items than can be displayed! ***");
				client->Message(0, "Remove items and re-loot corpse to access remaining inventory.");
				client->Message(0, "(%s contains %i additional %s.)", GetName(), (i - corpselootlimit), (i - corpselootlimit) == 1 ? "item" : "items");
			}

			if(IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, player corpse contains items, but client doesn't see them...
				client->Message(13, "This corpse contains items that are inaccessable!");
				client->Message(15, "Contact a GM for item replacement, if necessary.");
				client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetCorpseDBID(), GetName(), itemlist.size());

				cur = itemlist.begin();
				end = itemlist.end();
				for(; cur != end; ++cur) {
					ServerLootItem_Struct* item_data = *cur;
					item = database.GetItem(item_data->item_id);
					Log.Out(Logs::General, Logs::None, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
					client->Message(0, "Inaccessable Corpse Item: %s", item->Name);
				}
			}
		}
	}

	// Disgrace: Client seems to require that we send the packet back...
	client->QueuePacket(app);

	// This is required for the 'Loot All' feature to work for SoD clients. I expect it is to tell the client that the
	// server has now sent all the items on the corpse.
	if(client->GetClientVersion() >= ClientVersion::SoD) { SendLootReqErrorPacket(client, 6); }
}
Example #30
0
void Corpse::Spawn() {
	EQApplicationPacket* app = new EQApplicationPacket;
	this->CreateSpawnPacket(app, this);
	entity_list.QueueClients(this, app);
	safe_delete(app);
}