diff --git a/doc/script_commands.txt b/doc/script_commands.txt index b8f6e9ace..b7c3bdf65 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -230,3 +230,8 @@ spell_scripts * datalong2 = creature entry (searching for a buddy, closest to source) * datalong3 = creature search radius * data_flags = flag_target_as_source = 0x01 +29 SCRIPT_COMMAND_MODIFY_NPC_FLAGS source=worldobject or target=worldobject (datalong1==0), else source or target = creature + * datalong=NPCFlags + * datalong1=creature entry + * datalong2=search radius + * data_flags = 0x00=toggle, 0x01=add, 0x02=remove diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 2792d7bfa..42ca83996 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -2513,7 +2513,7 @@ void Map::ScriptsProcess() if (target && target->GetTypeId() == TYPEID_UNIT) pMover = (Creature*)target; } - else if (pSource->GetTypeId() == TYPEID_UNIT) + else pMover = (Creature*)pSource; } else // If step has a buddy entry defined, search for it @@ -2574,7 +2574,7 @@ void Map::ScriptsProcess() if (target && target->GetTypeId() == TYPEID_UNIT) pOwner = (Creature*)target; } - else if (pSource->GetTypeId() == TYPEID_UNIT) + else pOwner = (Creature*)pSource; } else // If step has a buddy entry defined, search for it @@ -2620,7 +2620,7 @@ void Map::ScriptsProcess() if (target && target->GetTypeId() == TYPEID_UNIT) pOwner = (Creature*)target; } - else if (pSource->GetTypeId() == TYPEID_UNIT) + else pOwner = (Creature*)pSource; } else // If step has a buddy entry defined, search for it @@ -2670,7 +2670,7 @@ void Map::ScriptsProcess() if (target && target->GetTypeId() == TYPEID_UNIT) pOwner = (Creature*)target; } - else if (pSource->GetTypeId() == TYPEID_UNIT) + else pOwner = (Creature*)pSource; } else // If step has a buddy entry defined, search for it @@ -2727,7 +2727,7 @@ void Map::ScriptsProcess() if (target && target->GetTypeId() == TYPEID_UNIT) pOwner = (Creature*)target; } - else if (pSource->GetTypeId() == TYPEID_UNIT) + else pOwner = (Creature*)pSource; } else // If step has a buddy entry defined, search for it @@ -2784,7 +2784,7 @@ void Map::ScriptsProcess() if (target && target->GetTypeId() == TYPEID_UNIT) pOwner = (Creature*)target; } - else if (pSource->GetTypeId() == TYPEID_UNIT) + else pOwner = (Creature*)pSource; } else // If step has a buddy entry defined, search for it @@ -2963,8 +2963,66 @@ void Map::ScriptsProcess() ((Unit*)pSource)->SetStandState(step.script->standState.stand_state); break; } + case SCRIPT_COMMAND_MODIFY_NPC_FLAGS: + { + if (!source && !target) + { + sLog.outError("SCRIPT_COMMAND_MODIFY_NPC_FLAGS (script id %u) call for NULL source and NULL target.", step.script->id); + break; + } + + if ((!source || !source->isType(TYPEMASK_WORLDOBJECT)) && (!target || !target->isType(TYPEMASK_WORLDOBJECT))) + { + sLog.outError("SCRIPT_COMMAND_MODIFY_NPC_FLAGS (script id %u) call for unsupported non-worldobject (TypeId: %u), skipping.", step.script->id, source ? source->GetTypeId() : target->GetTypeId()); + break; + } + + WorldObject* pSource = source && source->isType(TYPEMASK_WORLDOBJECT) ? (WorldObject*)source : (WorldObject*)target; + Creature* pBuddy = NULL; + + // No buddy defined, so try use source (or target if source is not creature) + if (!step.script->npcFlag.creatureEntry) + { + if (pSource->GetTypeId() != TYPEID_UNIT) + { + // we can't be non-creature, so see if target is creature + if (target && target->GetTypeId() == TYPEID_UNIT) + pBuddy = (Creature*)target; + } + else + pBuddy = (Creature*)pSource; + } + else // If step has a buddy entry defined, search for it + { + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*pSource, step.script->npcFlag.creatureEntry, true, step.script->npcFlag.searchRadius); + MaNGOS::CreatureLastSearcher searcher(pBuddy, u_check); + + Cell::VisitGridObjects(pSource, searcher, step.script->npcFlag.searchRadius); + } + + if (!pBuddy) + { + sLog.outError("SCRIPT_COMMAND_MODIFY_NPC_FLAGS (script id %u) call for non-creature (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + // Add Flags + if (step.script->npcFlag.data_flags & 0x01) + pBuddy->SetFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + // Remove Flags + else if (step.script->npcFlag.data_flags & 0x02) + pBuddy->RemoveFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + // Toggle Flags + else + { + if (pBuddy->HasFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag)) + pBuddy->RemoveFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + else + pBuddy->SetFlag(UNIT_NPC_FLAGS, step.script->npcFlag.flag); + } + } default: - sLog.outError("Unknown SCRIPT_COMMAND_ %u called for script id %u.",step.script->command, step.script->id); + 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 16a45cfe6..00c0d21c3 100644 --- a/src/game/ScriptMgr.cpp +++ b/src/game/ScriptMgr.cpp @@ -578,6 +578,21 @@ void ScriptMgr::LoadScripts(ScriptMapMap& scripts, const char* tablename) } break; } + case SCRIPT_COMMAND_MODIFY_NPC_FLAGS: + { + if (tmp.npcFlag.creatureEntry && !ObjectMgr::GetCreatureTemplate(tmp.npcFlag.creatureEntry)) + { + sLog.outErrorDb("Table `%s` has datalong3 = %u in SCRIPT_COMMAND_MODIFY_NPC_FLAGS for script id %u, but this creature_template does not exist.", tablename, tmp.run.creatureEntry, tmp.id); + continue; + } + if (tmp.npcFlag.creatureEntry && !tmp.npcFlag.searchRadius) + { + sLog.outErrorDb("Table `%s` has datalong3 = %u in SCRIPT_COMMAND_MODIFY_NPC_FLAGS for script id %u, but search radius is too small (datalong4 = %u).", tablename, tmp.run.creatureEntry, tmp.id, tmp.run.searchRadius); + continue; + } + + break; + } } if (scripts.find(tmp.id) == scripts.end()) diff --git a/src/game/ScriptMgr.h b/src/game/ScriptMgr.h index ee950d5cf..127d3da97 100644 --- a/src/game/ScriptMgr.h +++ b/src/game/ScriptMgr.h @@ -99,6 +99,10 @@ enum eScriptCommand // 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 + SCRIPT_COMMAND_MODIFY_NPC_FLAGS = 29, // source=worldobject or target=worldobject (datalong1==0), else creature + // datalong=NPCFlags + // datalong1=creature entry, datalong2=search radius + // data_flags = 0x01=add, 0x02=remove }; #define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK @@ -307,6 +311,16 @@ struct ScriptInfo uint32 flags; // data_flags } standState; + struct // SCRIPT_COMMAND_MODIFY_NPC_FLAGS (29) + { + uint32 flag; // datalong + uint32 creatureEntry; // datalong1 + uint32 searchRadius; // datalong2 + uint32 empty1; // datalong3 + uint32 empty2; // datalong4 + uint32 data_flags; // data_flags + } npcFlag; + struct { uint32 data[9]; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 002ba1285..f95738e7a 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 "11822" + #define REVISION_NR "11823" #endif // __REVISION_NR_H__