Skip to content

Commit

Permalink
[11558] Fixes and way work chnages for GO lock/interact state
Browse files Browse the repository at this point in the history
* Not reset lock/interact state in instances (so until instance reset)
* Do unti-cheating checks for use attempts locked/non-intareactive GOs
* Implement SCRIPT_COMMAND_GO_LOCK_STATE for control lock/interact state of GOs from scripts.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
  • Loading branch information
Schmoozerd authored and VladimirMangos committed May 29, 2011
1 parent 7c9419c commit 13c9f4e
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 10 deletions.
11 changes: 5 additions & 6 deletions doc/script_commands.txt
Expand Up @@ -218,9 +218,8 @@ spell_scripts
* datalong3 = creature search radius
* data_flags = flag_original_source_as_target = 0x02
flag_buddy_as_target = 0x04 (When this flag is not set, buddy will be the attacker when buddy is defined)






27 SCRIPT_COMMAND_GO_LOCK_STATE source or target must be WorldObject
* datalong = flag_go_lock = 0x01, flag_go_unlock = 0x02,
flag_go_nonInteract = 0x04, flag_go_interact = 0x08
* datalong2 = go entry (searching closest to source (if worldobject) or target
* datalong3 = go search radius
7 changes: 5 additions & 2 deletions src/game/GameObject.cpp
Expand Up @@ -398,8 +398,11 @@ void GameObject::Update(uint32 update_diff, uint32 /*p_time*/)
if (GetGOInfo()->IsDespawnAtAction() || GetGoAnimProgress() > 0)
{
SendObjectDeSpawnAnim(GetObjectGuid());
//reset flags
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
// reset flags: In Instances do not restore GO_FLAG_LOCKED or GO_FLAG_NO_INTERACT
if (GetMap()->Instanceable())
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags & ~(GO_FLAG_LOCKED | GO_FLAG_NO_INTERACT));
else
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
}

loot.clear();
Expand Down
36 changes: 36 additions & 0 deletions src/game/Map.cpp
Expand Up @@ -2869,6 +2869,42 @@ void Map::ScriptsProcess()
sLog.outError("SCRIPT_COMMAND_ATTACK_START (script id %u) unexpected error, attacker or victim could not be found, no action.", step.script->id);
break;
}
case SCRIPT_COMMAND_GO_LOCK_STATE:
{
if ((!source || !source->isType(TYPEMASK_WORLDOBJECT)) && (!target || !target->isType(TYPEMASK_WORLDOBJECT)))
{
sLog.outError("SCRIPT_COMMAND_GO_LOCK_STATE (script id %u) call for non-worldobject (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0);
break;
}

WorldObject* pSearcher = source && source->isType(TYPEMASK_WORLDOBJECT) ? (WorldObject*)source : (WorldObject*)target;
GameObject* pGo = NULL;

MaNGOS::NearestGameObjectEntryInObjectRangeCheck u_check(*pSearcher, step.script->goLockState.goEntry, step.script->goLockState.searchRadius);
MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> searcher(pGo, u_check);

Cell::VisitGridObjects(pSearcher, searcher, step.script->goLockState.searchRadius);

/* flag lockState
* go_lock 0x01
* go_unlock 0x02
* go_nonInteract 0x04
* go_Interact 0x08
*/
if (pGo)
{
// Lock or Unlock
if (step.script->goLockState.lockState & 0x01)
pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
else if (step.script->goLockState.lockState & 0x02)
pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
// Set Non Interactable or Set Interactable
if (step.script->goLockState.lockState & 0x04)
pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT);
else if (step.script->goLockState.lockState & 0x08)
pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT);
}
}
default:
sLog.outError("Unknown SCRIPT_COMMAND_ %u called for script id %u.",step.script->command, step.script->id);
break;
Expand Down
26 changes: 26 additions & 0 deletions src/game/ScriptMgr.cpp
Expand Up @@ -533,6 +533,32 @@ void ScriptMgr::LoadScripts(ScriptMapMap& scripts, const char* tablename)
}
break;
}
case SCRIPT_COMMAND_GO_LOCK_STATE:
{
if (!ObjectMgr::GetGameObjectInfo(tmp.goLockState.goEntry))
{
sLog.outErrorDb("Table `%s` has datalong2 = %u in SCRIPT_COMMAND_GO_LOCK_STATE for script id %u, but this gameobject_template does not exist.", tablename, tmp.goLockState.goEntry, tmp.id);
continue;
}
if (!tmp.goLockState.searchRadius)
{
sLog.outErrorDb("Table `%s` has invalid search radius (datalong3 = %u) in SCRIPT_COMMAND_GO_LOCK_STATE for script id %u.", tablename, tmp.goLockState.searchRadius, tmp.id);
continue;
}
if (// lock(0x01) and unlock(0x02) together
((tmp.goLockState.lockState & 0x01) && (tmp.goLockState.lockState & 0x02)) ||
// non-interact (0x4) and interact (0x08) together
((tmp.goLockState.lockState & 0x04) && (tmp.goLockState.lockState & 0x08)) ||
// no setting
!tmp.goLockState.lockState ||
// invalid number
tmp.goLockState.lockState >= 0x10)
{
sLog.outErrorDb("Table `%s` has invalid lock state (datalong = %u) in SCRIPT_COMMAND_GO_LOCK_STATE for script id %u.", tablename, tmp.goLockState.lockState, tmp.id);
continue;
}
break;
}
}

if (scripts.find(tmp.id) == scripts.end())
Expand Down
10 changes: 10 additions & 0 deletions src/game/ScriptMgr.h
Expand Up @@ -92,6 +92,9 @@ enum eScriptCommand
// datalong2=creature entry, datalong3=search radius
SCRIPT_COMMAND_ATTACK_START = 26, // source = Creature (or WorldObject when creature entry are defined), target = Player
// datalong2 = creature entry (searching for a buddy, closest to source), datalong3 = creature search radius
SCRIPT_COMMAND_GO_LOCK_STATE = 27, // source or target must be WorldObject
// datalong= 1=lock, 2=unlock, 4=set not-interactable, 8=set interactable
// datalong2= go entry, datalong3= go search radius
};

#define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK
Expand Down Expand Up @@ -284,6 +287,13 @@ struct ScriptInfo
uint32 flags; // data_flags
} attack;

struct // SCRIPT_COMMAND_GO_LOCK_STATE (27)
{
uint32 lockState; // datalong
uint32 goEntry; // datalong2
uint32 searchRadius; // datalong3
} goLockState;

struct
{
uint32 data[9];
Expand Down
2 changes: 1 addition & 1 deletion src/game/SharedDefines.h
Expand Up @@ -1258,7 +1258,7 @@ enum GameObjectFlags
GO_FLAG_LOCKED = 0x00000002, //require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip
GO_FLAG_INTERACT_COND = 0x00000004, //cannot interact (condition to interact)
GO_FLAG_TRANSPORT = 0x00000008, //any kind of transport? Object can transport (elevator, boat, car)
GO_FLAG_UNK1 = 0x00000010, //
GO_FLAG_NO_INTERACT = 0x00000010, //players cannot interact with this go (often need to remove flag in event)
GO_FLAG_NODESPAWN = 0x00000020, //never despawn, typically for doors, they just change state
GO_FLAG_TRIGGERED = 0x00000040, //typically, summoned objects. Triggered by spell or other events
GO_FLAG_UNK_8 = 0x00000080,
Expand Down
14 changes: 14 additions & 0 deletions src/game/SpellHandler.cpp
Expand Up @@ -289,13 +289,27 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
if(!obj)
return;

// Additional check preventing exploits (ie loot despawned chests)
if (!obj->isSpawned())
{
sLog.outError("HandleGameObjectUseOpcode: CMSG_GAMEOBJ_USE for despawned GameObject (Entry %u), didn't expect this to happen.", obj->GetEntry());
return;
}

// Never expect this opcode for some type GO's
if (obj->GetGoType() == GAMEOBJECT_TYPE_GENERIC)
{
sLog.outError("HandleGameObjectUseOpcode: CMSG_GAMEOBJ_USE for not allowed GameObject type %u (Entry %u), didn't expect this to happen.", obj->GetGoType(), obj->GetEntry());
return;
}

// Never expect this opcode for non intractable GO's
if (obj->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT))
{
sLog.outError("HandleGameObjectUseOpcode: CMSG_GAMEOBJ_USE for GameObject (Entry %u) with non intractable flag (Flags %u), didn't expect this to happen.", obj->GetEntry(), obj->GetUInt32Value(GAMEOBJECT_FLAGS));
return;
}

obj->Use(_player);
}

Expand Down
2 changes: 1 addition & 1 deletion src/shared/revision_nr.h
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11557"
#define REVISION_NR "11558"
#endif // __REVISION_NR_H__

0 comments on commit 13c9f4e

Please sign in to comment.