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); } } } }
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); } } } }