Example #1
0
void Doors::HandleClick(Client* sender, uint8 trigger)
{
	//door debugging info dump
	Log.Out(Logs::Detail, Logs::Doors, "%s clicked door %s (dbid %d, eqid %d) at %s", sender->GetName(), door_name, db_id, door_id, to_string(m_Position).c_str());
	Log.Out(Logs::Detail, Logs::Doors, "  incline %d, opentype %d, lockpick %d, keys %d %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, altkeyitem, nokeyring, trigger_door, trigger_type, door_param);
	Log.Out(Logs::Detail, Logs::Doors, "  size %d, invert %d, dest: %s %s", size, invert_state, dest_zone, to_string(m_Destination).c_str());

	EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
	MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
	md->doorid = door_id;
	/////////////////////////////////////////////////////////////////
	//used_pawn: Locked doors! Rogue friendly too =)
	//TODO: add check for other lockpick items
	//////////////////////////////////////////////////////////////////

	uint32 keyneeded = GetKeyItem();
	uint32 altkey = GetAltKeyItem();
	uint8 keepoffkeyring = GetNoKeyring();
	uint32 haskey = 0;
	uint32 hasaltkey = 0;
	uint32 playerkey = 0;
	const ItemInst *lockpicks = sender->GetInv().GetItem(MainCursor);

	haskey = sender->GetInv().HasItem(keyneeded, 1, invWhereCursor);
	hasaltkey = sender->GetInv().HasItem(altkey, 1, invWhereCursor);

	if(haskey == MainCursor)
	{
		playerkey = keyneeded;
	}
	else if(hasaltkey == MainCursor)
	{
		playerkey = altkey;
	}

	if(GetTriggerType() == 255)
	{ // this object isnt triggered
		if(trigger == 1)
		{ // this door is only triggered by an object
			if(!IsDoorOpen() || (opentype == 58))
			{
				md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
			}
			else
			{
				md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
			}
		}
		else
		{
			safe_delete(outapp);
			return;
		}
	}

	// guild doors
	if(((keyneeded == 0 && altkey == 0) && (GetLockpick() == 0) && (guild_id == 0)) ||
		(IsDoorOpen() && (opentype == 58)) ||
		((guild_id > 0) && (guild_id == sender->GuildID())))
	{	//door not locked
		if(!IsDoorOpen() || (opentype == 58))
		{
			md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
		}
		else
		{
			md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
		}
	}
	else
	{	// guild doors
		if((guild_id > 0) && !sender->GetGM())
		{
			std::string tmp;
			char tmpmsg[240]; // guild doors msgs
			if(guild_mgr.GetGuildNameByID(guild_id, tmp))
			{
				sprintf(tmpmsg, "Only members of the <%s> guild may enter here", tmp.c_str());
			}
			else
			{
				strcpy(tmpmsg, "Door is locked by an unknown guild");
			}
			sender->Message(CC_Blue, tmpmsg);
			safe_delete(outapp);
			return;
		}
		// a key is required or the door is locked but can be picked or both
		sender->Message(CC_Blue, "This is locked...");		// debug spam - should probably go
		if(sender->GetGM())		// GM can always open locks
		{
			sender->Message_StringID(CC_Blue,DOORS_GM);
			if(!IsDoorOpen() || (opentype == 58))
			{
				md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
			}
			else
			{
				md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
			}
		}
		else if(playerkey)
		{	// they have something they are trying to open it with
			if(keyneeded && (keyneeded == playerkey) || altkey && (altkey == playerkey))
			{	// key required and client is using the right key
				if(!keepoffkeyring)
				{
					sender->KeyRingAdd(playerkey);
				}
				sender->Message(CC_Blue, "You got it open!");
				if(!IsDoorOpen() || (opentype == 58))
				{
					md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
				}
				else
				{
					md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
				}
			}
		}
		else if(lockpicks != nullptr)
		{
			if(sender->GetSkill(SkillPickLock))
			{
				if(lockpicks->GetItem()->ItemType == ItemTypeLockPick)
				{
					float modskill=sender->GetSkill(SkillPickLock);

					// Lockpicks will be on the cursor and not equipped, so we need to manually get any skillmod they may have.
					if(lockpicks->GetItem()->SkillModType == SkillPickLock) 
					{
						modskill += modskill * (static_cast<float>(lockpicks->GetItem()->SkillModValue)/100.0);
					}

					Log.Out(Logs::General, Logs::Skills, "Client has lockpicks: skill=%f", modskill);

					if(GetLockpick() <= modskill)
					{
						if(!IsDoorOpen())
						{
							sender->CheckIncreaseSkill(SkillPickLock, nullptr, zone->skill_difficulty[SkillPickLock].difficulty, 1.0);
							md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
						}
						else
						{
							md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
						}
						sender->Message_StringID(CC_Blue, DOORS_SUCCESSFUL_PICK);
					}
					else
					{
						sender->Message_StringID(CC_Blue, DOORS_INSUFFICIENT_SKILL);
						safe_delete(outapp);
						return;
					}
				}
				else
				{
					sender->Message_StringID(CC_Blue, DOORS_NO_PICK);
					safe_delete(outapp);
					return;
				}
			}
			else
			{
				sender->Message_StringID(CC_Blue, DOORS_CANT_PICK);
				safe_delete(outapp);
				return;
			}
		}
		else
		{	// locked door and nothing to open it with
			// search for key on keyring
			uint32 keyring = 0;
			if(sender->KeyRingCheck(keyneeded))
				keyring = keyneeded;
			else if(sender->KeyRingCheck(altkey))
				keyring = altkey;

			if(keyring > 0)
			{
				playerkey = keyring;
				sender->Message(CC_Blue, "You got it open!"); // more debug spam
				if(!IsDoorOpen() || (opentype == 58))
				{
					md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
				}
				else
				{
					md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
				}
			}
			else
			{
				sender->Message_StringID(CC_Blue, DOORS_LOCKED);
				safe_delete(outapp);
				return;
			}
		}
	}

	entity_list.QueueClients(sender, outapp, false);
	if(!IsDoorOpen() || (opentype == 58))
	{
		close_timer.Start();
		SetOpenState(true);
	}
	else
	{
		close_timer.Disable();
		SetOpenState(false);
	}

	//everything past this point assumes we opened the door
	//and met all the reqs for opening
	//everything to do with closed doors has already been taken care of
	//we return because we don't want people using teleports on an unlocked door (exploit!)
	if((md->action == CLOSE_DOOR && invert_state == 0) || (md->action == CLOSE_INVDOOR && invert_state == 1))
	{
		safe_delete(outapp);
		return;
	}

	safe_delete(outapp);

	if((GetTriggerDoorID() != 0) && (GetTriggerType() == 1))
	{
		Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
		if(triggerdoor && !triggerdoor->triggered)
		{
			triggered=true;
			triggerdoor->HandleClick(sender, 1);
		}
		else
		{
			triggered=false;
		}
	}
	else if((GetTriggerDoorID() != 0) && (GetTriggerType() != 1))
	{
		Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
		if(triggerdoor && !triggerdoor->triggered)
		{
			triggered=true;
			triggerdoor->HandleClick(sender, 0);
		}
		else
		{
			triggered=false;
		}
	}

	if(((opentype == 57) || (opentype == 58)) && (strncmp(dest_zone, "NONE", strlen("NONE")) != 0))
	{ // Teleport door!
		if (( strncmp(dest_zone,zone_name,strlen(zone_name)) == 0) && (!keyneeded))
		{
			if(!keepoffkeyring)
			{
				sender->KeyRingAdd(playerkey);
			}
			sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
		}
		else if (( !IsDoorOpen() || opentype == 58 ) && (keyneeded && ((keyneeded == playerkey) || sender->GetGM())))
		{
			if(!keepoffkeyring)
			{
				sender->KeyRingAdd(playerkey);
			}
			if(database.GetZoneID(dest_zone) == zone->GetZoneID())
			{
				sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
			}
			else
			{
				sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
			}
		}
		if (( !IsDoorOpen() || opentype == 58 ) && (!keyneeded))
		{
			if(database.GetZoneID(dest_zone) == zone->GetZoneID())
			{
				sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
			}
			else
			{
				sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
			}
		}
	}
}
Example #2
0
void Doors::HandleClick(Client* sender, uint8 trigger)
{
	//door debugging info dump
	_log(DOORS__INFO, "%s clicked door %s (dbid %d, eqid %d) at (%.4f,%.4f,%.4f @%.4f)", sender->GetName(), door_name, db_id, door_id, pos_x, pos_y, pos_z, heading);
	_log(DOORS__INFO, "  incline %d, opentype %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param);
	_log(DOORS__INFO, "  size %d, invert %d, dest: %s (%.4f,%.4f,%.4f @%.4f)", size, invert_state, dest_zone, dest_x, dest_y, dest_z, dest_heading);

	EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
	MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
	md->doorid = door_id;
	/////////////////////////////////////////////////////////////////
	//used_pawn: Locked doors! Rogue friendly too =)
	//TODO: add check for other lockpick items
	//////////////////////////////////////////////////////////////////

	//TODO: ADVENTURE DOOR
	if(IsLDoNDoor())
	{
		if(sender)
		{
			if(RuleI(Adventure, ItemIDToEnablePorts) != 0)
			{
				if(!sender->KeyRingCheck(RuleI(Adventure, ItemIDToEnablePorts)))
				{
					if(sender->GetInv().HasItem(RuleI(Adventure, ItemIDToEnablePorts)) == SLOT_INVALID)
					{
						sender->Message_StringID(13, 5141);
						safe_delete(outapp);
						return;
					}
					else
					{
						sender->KeyRingAdd(RuleI(Adventure, ItemIDToEnablePorts));
					}
				}
			}

			if(!sender->GetPendingAdventureDoorClick())
			{
				sender->PendingAdventureDoorClick();
				ServerPacket *pack = new ServerPacket(ServerOP_AdventureClickDoor, sizeof(ServerPlayerClickedAdventureDoor_Struct));
				ServerPlayerClickedAdventureDoor_Struct *ads = (ServerPlayerClickedAdventureDoor_Struct*)pack->pBuffer;
				strcpy(ads->player, sender->GetName());
				ads->zone_id = zone->GetZoneID();
				ads->id = GetDoorDBID();
				worldserver.SendPacket(pack);
				safe_delete(pack);
				safe_delete(outapp);
			}
			return;
		}
	}

	uint32 keyneeded = GetKeyItem();
	uint8 keepoffkeyring = GetNoKeyring();
	uint32 haskey = 0;
	uint32 playerkey = 0;
	const ItemInst *lockpicks = sender->GetInv().GetItem(SLOT_CURSOR);

	haskey = sender->GetInv().HasItem(keyneeded, 1);

	if(haskey != SLOT_INVALID)
	{
		playerkey = keyneeded;
	}

	if(GetTriggerType() == 255)
	{ // this object isnt triggered
		if(trigger == 1)
		{ // this door is only triggered by an object
			if(!IsDoorOpen() || (opentype == 58))
			{
				md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
			}
			else
			{
				md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
			}
		}
		else
		{
			safe_delete(outapp);
			return;
		}
	}

	// guild doors
	if(((keyneeded == 0) && (GetLockpick() == 0) && (guild_id == 0)) ||
		(IsDoorOpen() && (opentype == 58)) ||
		((guild_id > 0) && (guild_id == sender->GuildID())))
	{	//door not locked
		if(!IsDoorOpen() || (opentype == 58))
		{
			md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
		}
		else
		{
			md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
		}
	}
	else
	{	// guild doors
		if((guild_id > 0) && !sender->GetGM())
		{
			std::string tmp;
			char tmpmsg[240]; // guild doors msgs
			if(guild_mgr.GetGuildNameByID(guild_id, tmp))
			{
				sprintf(tmpmsg, "Only members of the <%s> guild may enter here", tmp.c_str());
			}
			else
			{
				strcpy(tmpmsg, "Door is locked by an unknown guild");
			}
			sender->Message(4, tmpmsg);
			// safe_delete(outapp);
			// /\ possible missing line..all other 'fail' returns seem to have it
			return;
		}
		// a key is required or the door is locked but can be picked or both
		sender->Message(4, "This is locked...");		// debug spam - should probably go
		if(sender->GetGM())		// GM can always open locks - should probably be changed to require a key
		{
			sender->Message_StringID(4,DOORS_GM);
			if(!IsDoorOpen() || (opentype == 58))
			{
				md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
			}
			else
			{
				md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
			}
		}
		else if(playerkey)
		{	// they have something they are trying to open it with
			if(keyneeded && (keyneeded == playerkey))
			{	// key required and client is using the right key
				if(!keepoffkeyring)
				{
					sender->KeyRingAdd(playerkey);
				}
				sender->Message(4, "You got it open!");
				if(!IsDoorOpen() || (opentype == 58))
				{
					md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
				}
				else
				{
					md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
				}
			}
		}
		else if(lockpicks != nullptr)
		{
			if(sender->GetSkill(PICK_LOCK))
			{
				if(lockpicks->GetItem()->ItemType == ItemTypeLockPick)
				{
					float modskill=sender->GetSkill(PICK_LOCK);
					sender->CheckIncreaseSkill(PICK_LOCK, nullptr, 1);

#if EQDEBUG>=5
					LogFile->write(EQEMuLog::Debug, "Client has lockpicks: skill=%f", modskill);
#endif

					if(GetLockpick() <= modskill)
					{
						if(!IsDoorOpen())
						{
							md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
						}
						else
						{
							md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
						}
						sender->Message_StringID(4, DOORS_SUCCESSFUL_PICK);
					}
					else
					{
						sender->Message_StringID(4, DOORS_INSUFFICIENT_SKILL);
						safe_delete(outapp);
						return;
					}
				}
				else
				{
					sender->Message_StringID(4, DOORS_NO_PICK);
					safe_delete(outapp);
					return;
				}
			}
			else
			{
				sender->Message_StringID(4, DOORS_CANT_PICK);
				safe_delete(outapp);
				return;
			}
		}
		else
		{	// locked door and nothing to open it with
			// search for key on keyring
			if(sender->KeyRingCheck(keyneeded))
			{
				playerkey = keyneeded;
				sender->Message(4, "You got it open!"); // more debug spam
				if(!IsDoorOpen() || (opentype == 58))
				{
					md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
				}
				else
				{
					md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
				}
			}
			else
			{
				sender->Message_StringID(4, DOORS_LOCKED);
				safe_delete(outapp);
				return;
			}
		}
	}

	entity_list.QueueClients(sender, outapp, false);
	if(!IsDoorOpen() || (opentype == 58))
	{
		close_timer.Start();
		SetOpenState(true);
	}
	else
	{
		close_timer.Disable();
		SetOpenState(false);
	}

	//everything past this point assumes we opened the door
	//and met all the reqs for opening
	//everything to do with closed doors has already been taken care of
	//we return because we don't want people using teleports on an unlocked door (exploit!)
	if((md->action == CLOSE_DOOR && invert_state == 0) || (md->action == CLOSE_INVDOOR && invert_state == 1))
	{
		safe_delete(outapp);
		return;
	}

	safe_delete(outapp);

	if((GetTriggerDoorID() != 0) && (GetTriggerType() == 1))
	{
		Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
		if(triggerdoor && !triggerdoor->triggered)
		{
			triggered=true;
			triggerdoor->HandleClick(sender, 1);
		}
		else
		{
			triggered=false;
		}
	}
	else if((GetTriggerDoorID() != 0) && (GetTriggerType() != 1))
	{
		Doors* triggerdoor = entity_list.FindDoor(GetTriggerDoorID());
		if(triggerdoor && !triggerdoor->triggered)
		{
			triggered=true;
			triggerdoor->HandleClick(sender, 0);
		}
		else
		{
			triggered=false;
		}
	}

	if(((opentype == 57) || (opentype == 58)) && (strncmp(dest_zone, "NONE", strlen("NONE")) != 0))
	{ // Teleport door!
		if (( strncmp(dest_zone,zone_name,strlen(zone_name)) == 0) && (!keyneeded))
		{
			if(!keepoffkeyring)
			{
				sender->KeyRingAdd(playerkey);
			}
			sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
		}
		else if (( !IsDoorOpen() || opentype == 58 ) && (keyneeded && ((keyneeded == playerkey) || sender->GetGM())))
		{
			if(!keepoffkeyring)
			{
				sender->KeyRingAdd(playerkey);
			}
			if(database.GetZoneID(dest_zone) == zone->GetZoneID())
			{
				sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
			}
			else
			{
				sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, dest_x, dest_y, dest_z, dest_heading);
			}
		}
		if (( !IsDoorOpen() || opentype == 58 ) && (!keyneeded))
		{
			if(database.GetZoneID(dest_zone) == zone->GetZoneID())
			{
				sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
			}
			else
			{
				sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, dest_x, dest_y, dest_z, dest_heading);
			}
		}
	}
}