diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 11f584ab0..12b6a2831 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -218,8 +218,15 @@ 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 + +28 SCRIPT_COMMAND_EMOTE source = Unit (or WorldObject when creature entry defined), target = Unit (or none) + * datalong = stand state (enum UnitStandStateType) + * datalong2 = creature entry (searching for a buddy, closest to source) + * datalong3 = creature search radius + * data_flags = flag_target_as_source = 0x01 diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 93ecac1ac..a695af412 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -2905,6 +2905,57 @@ void Map::ScriptsProcess() pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); } } + case SCRIPT_COMMAND_STAND_STATE: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_STAND_STATE (script id %u) call for NULL source.", step.script->id); + break; + } + + if (!source->isType(TYPEMASK_WORLDOBJECT)) + { + sLog.outError("SCRIPT_COMMAND_STAND_STATE (script id %u) call for non-worldobject (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); + break; + } + // When creatureEntry is not defined, GameObject can not be source + else if (!step.script->standState.creatureEntry) + { + if (!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_STAND_STATE (script id %u) are missing datalong2 (creature entry). Unsupported call for non-unit (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); + break; + } + } + + WorldObject* pSource = (WorldObject*)source; + Creature* pBuddy = NULL; + + // flag_target_as_source 0x01 + + // If target is Unit* and should change it's stand state (or should be source of searcher below) + if (target && target->isType(TYPEMASK_UNIT) && step.script->standState.flags & 0x01) + pSource = (WorldObject*)target; + + // If step has a buddy entry defined, search for it. + if (step.script->standState.creatureEntry) + { + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*pSource, step.script->standState.creatureEntry, true, step.script->standState.searchRadius); + MaNGOS::CreatureLastSearcher searcher(pBuddy, u_check); + + Cell::VisitGridObjects(pSource, searcher, step.script->standState.searchRadius); + + // If buddy found, then use it or break (break since we must assume pBuddy was defined for a reason) + if (pBuddy) + pSource = (WorldObject*)pBuddy; + else + break; + } + + // Must be safe cast to Unit* here + ((Unit*)pSource)->SetStandState(step.script->standState.stand_state); + break; + } default: sLog.outError("Unknown SCRIPT_COMMAND_ %u called for script id %u.",step.script->command, step.script->id); break; diff --git a/src/game/ScriptMgr.cpp b/src/game/ScriptMgr.cpp index 05ac6c4ff..f0a4d7c5d 100644 --- a/src/game/ScriptMgr.cpp +++ b/src/game/ScriptMgr.cpp @@ -559,6 +559,25 @@ void ScriptMgr::LoadScripts(ScriptMapMap& scripts, const char* tablename) } break; } + case SCRIPT_COMMAND_STAND_STATE: + { + if (tmp.standState.stand_state > UNIT_STAND_STATE_CUSTOM) + { + sLog.outErrorDb("Table `%s` has invalid stand state (datalong = %u) in SCRIPT_COMMAND_STAND_STATE for script id %u", tablename, tmp.standState.stand_state, tmp.id); + continue; + } + if (tmp.standState.creatureEntry && !ObjectMgr::GetCreatureTemplate(tmp.standState.creatureEntry)) + { + sLog.outErrorDb("Table `%s` has datalong2 = %u in SCRIPT_COMMAND_STAND_STATE for script id %u, but this creature_template does not exist.", tablename, tmp.standState.creatureEntry, tmp.id); + continue; + } + if (tmp.standState.creatureEntry && !tmp.standState.searchRadius) + { + sLog.outErrorDb("Table `%s` has datalong2 = %u in SCRIPT_COMMAND_STAND_STATE for script id %u, but search radius is too small (datalong3 = %u).", tablename, tmp.standState.creatureEntry, tmp.id, tmp.standState.searchRadius); + continue; + } + break; + } } if (scripts.find(tmp.id) == scripts.end()) diff --git a/src/game/ScriptMgr.h b/src/game/ScriptMgr.h index 9fa6b6662..ee950d5cf 100644 --- a/src/game/ScriptMgr.h +++ b/src/game/ScriptMgr.h @@ -95,6 +95,10 @@ enum eScriptCommand 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 + SCRIPT_COMMAND_STAND_STATE = 28, // source = Unit (or WorldObject when creature entry defined), target = Unit (or none) + // datalong = stand state (enum UnitStandStateType) + // datalong2 = creature entry (searching for a buddy, closest to source), datalong3 = creature search radius + // data_flags = flag_target_as_source = 0x01 }; #define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK @@ -294,6 +298,15 @@ struct ScriptInfo uint32 searchRadius; // datalong3 } goLockState; + struct // SCRIPT_COMMAND_STAND_STATE (28) + { + uint32 stand_state; // datalong + uint32 creatureEntry; // datalong2 + uint32 searchRadius; // datalong3 + uint32 unused1; // datalong4 + uint32 flags; // data_flags + } standState; + struct { uint32 data[9]; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1c3c26f8d..a9dc17737 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11581" + #define REVISION_NR "11582" #endif // __REVISION_NR_H__