From 31ec245b68d6dc1763237901498f1220bbdaa212 Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Thu, 13 May 2010 16:38:15 +0200 Subject: [PATCH] [9889] Extend features available for SCRIPT_COMMAND_TALK * Allow other than Creature to talk. * Add "buddy-talk", using creature entry in datalong2 (the npc who will do the talk instead of the original source). Value in datalong3 is how far to look for the buddy. * Add data_flags making it possible to have conversations between units, controlling who does the talking and to whom, including make player do the talking when player is not already the source. Notes and details are added in the comments for SCRIPT_COMMAND_TALK Signed-off-by: NoFantasy --- src/game/Map.cpp | 73 ++++++++++++++++++++++++++++++++-------- src/game/ObjectMgr.cpp | 22 ++++++++---- src/game/World.h | 6 +++- src/shared/revision_nr.h | 2 +- 4 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/game/Map.cpp b/src/game/Map.cpp index d8ad165bb..b256ac60a 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -2856,50 +2856,95 @@ void Map::ScriptsProcess() { if (!source) { - sLog.outError("SCRIPT_COMMAND_TALK (script id %u) call for NULL creature.", step.script->id); + sLog.outError("SCRIPT_COMMAND_TALK (script id %u) call for NULL source.", step.script->id); break; } - if (source->GetTypeId() != TYPEID_UNIT) + WorldObject* pSource = dynamic_cast(source); + + if (!pSource) { - sLog.outError("SCRIPT_COMMAND_TALK (script id %u) call for non-creature (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); + sLog.outError("SCRIPT_COMMAND_TALK (script id %u) call for unsupported non-worldobject (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); break; } + Creature* pBuddy = NULL; + + // flag_target_player_as_source 0x01 + // flag_original_source_as_target 0x02 + // flag_buddy_as_target 0x04 + + // If target is player (and not already the source) but should be the source + if (target && target->GetTypeId() == TYPEID_PLAYER && step.script->data_flags & 0x01) + { + if (source->GetTypeId() != TYPEID_PLAYER) + pSource = (WorldObject*)target; + } + + // If step has a buddy entry defined, search for it. + if (step.script->datalong2) + { + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*pSource, step.script->datalong2, true, step.script->datalong3); + MaNGOS::CreatureLastSearcher searcher(pSource, pBuddy, u_check); + + Cell::VisitGridObjects(pSource, searcher, step.script->datalong3); + } + + // If buddy found, then use it + if (pBuddy) + { + // pBuddy can be target of talk + if (step.script->data_flags & 0x04) + { + target = (Object*)pBuddy; + } + else + { + // If not target of talk, then set pBuddy as source + // Useless when source is already flagged to be player, and should maybe produce error. + if (!(step.script->data_flags & 0x01)) + pSource = (WorldObject*)pBuddy; + } + } + + // If we should talk to the original source instead of target + if (step.script->data_flags & 0x02) + target = source; + uint64 unit_target = target ? target->GetGUID() : 0; switch(step.script->datalong) { case CHAT_TYPE_SAY: - ((Creature*)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target); + pSource->MonsterSay(step.script->dataint, LANG_UNIVERSAL, unit_target); break; case CHAT_TYPE_YELL: - ((Creature*)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target); + pSource->MonsterYell(step.script->dataint, LANG_UNIVERSAL, unit_target); break; case CHAT_TYPE_TEXT_EMOTE: - ((Creature*)source)->TextEmote(step.script->dataint, unit_target); + pSource->MonsterTextEmote(step.script->dataint, unit_target); break; case CHAT_TYPE_BOSS_EMOTE: - ((Creature*)source)->TextEmote(step.script->dataint, unit_target, true); + pSource->MonsterTextEmote(step.script->dataint, unit_target, true); break; case CHAT_TYPE_WHISPER: - if (!unit_target) + if (!unit_target || !IS_PLAYER_GUID(unit_target)) { - sLog.outError("SCRIPT_COMMAND_TALK (script id %u) attempt to whisper (%u) 0-guid, skipping.", step.script->id, step.script->datalong); + sLog.outError("SCRIPT_COMMAND_TALK (script id %u) attempt to whisper (%u) 0-guid or non-player, skipping.", step.script->id, step.script->datalong); break; } - ((Creature*)source)->Whisper(step.script->dataint, unit_target); + pSource->MonsterWhisper(step.script->dataint, unit_target); break; case CHAT_TYPE_BOSS_WHISPER: - if (!unit_target) + if (!unit_target || !IS_PLAYER_GUID(unit_target)) { - sLog.outError("SCRIPT_COMMAND_TALK (script id %u) attempt to whisper (%u) 0-guid, skipping.", step.script->id, step.script->datalong); + sLog.outError("SCRIPT_COMMAND_TALK (script id %u) attempt to whisper (%u) 0-guid or non-player, skipping.", step.script->id, step.script->datalong); break; } - ((Creature*)source)->Whisper(step.script->dataint, unit_target, true); + pSource->MonsterWhisper(step.script->dataint, unit_target, true); break; case CHAT_TYPE_ZONE_YELL: - ((Creature*)source)->YellToZone(step.script->dataint, LANG_UNIVERSAL, unit_target); + pSource->MonsterYellToZone(step.script->dataint, LANG_UNIVERSAL, unit_target); break; default: break; // must be already checked at load diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index aba985b86..50c1c84a4 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4200,19 +4200,29 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) { case SCRIPT_COMMAND_TALK: { - if(tmp.datalong > CHAT_TYPE_ZONE_YELL) + if (tmp.datalong > CHAT_TYPE_ZONE_YELL) { - sLog.outErrorDb("Table `%s` has invalid CHAT_TYPE_ (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.datalong,tmp.id); + sLog.outErrorDb("Table `%s` has invalid CHAT_TYPE_ (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u", tablename, tmp.datalong, tmp.id); continue; } - if(tmp.dataint==0) + if (tmp.datalong2 && !GetCreatureTemplate(tmp.datalong2)) { - sLog.outErrorDb("Table `%s` has invalid talk text id (dataint = %i) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,tmp.id); + sLog.outErrorDb("Table `%s` has datalong2 = %u in SCRIPT_COMMAND_TALK for script id %u, but this creature_template does not exist.", tablename, tmp.datalong2, tmp.id); continue; } - if(tmp.dataint < MIN_DB_SCRIPT_STRING_ID || tmp.dataint >= MAX_DB_SCRIPT_STRING_ID) + if (tmp.datalong2 && !tmp.datalong3) { - sLog.outErrorDb("Table `%s` has out of range text id (dataint = %i expected %u-%u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID,tmp.id); + sLog.outErrorDb("Table `%s` has datalong2 = %u in SCRIPT_COMMAND_TALK for script id %u, but search radius is too small (datalong3 = %u).", tablename, tmp.datalong2, tmp.id, tmp.datalong3); + continue; + } + if (tmp.dataint == 0) + { + sLog.outErrorDb("Table `%s` has invalid talk text id (dataint = %i) in SCRIPT_COMMAND_TALK for script id %u", tablename, tmp.dataint, tmp.id); + continue; + } + if (tmp.dataint < MIN_DB_SCRIPT_STRING_ID || tmp.dataint >= MAX_DB_SCRIPT_STRING_ID) + { + sLog.outErrorDb("Table `%s` has out of range text id (dataint = %i expected %u-%u) in SCRIPT_COMMAND_TALK for script id %u", tablename, tmp.dataint, MIN_DB_SCRIPT_STRING_ID, MAX_DB_SCRIPT_STRING_ID, tmp.id); continue; } diff --git a/src/game/World.h b/src/game/World.h index fb95ac6b8..b3360e0ce 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -386,7 +386,11 @@ enum RealmZone }; // DB scripting commands -#define SCRIPT_COMMAND_TALK 0 // source = unit, target=any, datalong (see enum ChatType for supported CHAT_TYPE_'s) +#define SCRIPT_COMMAND_TALK 0 // source = WorldObject, target = any/none, datalong (see enum ChatType for supported CHAT_TYPE_'s) + // datalong2 = creature entry (searching for a buddy, closest to source), datalong3 = creature search radius + // data_flags = flag_target_player_as_source = 0x01 + // flag_original_source_as_target = 0x02 + // flag_buddy_as_target = 0x04 #define SCRIPT_COMMAND_EMOTE 1 // source = unit, datalong = anim_id #define SCRIPT_COMMAND_FIELD_SET 2 // source = any, datalong = field_id, datalog2 = value #define SCRIPT_COMMAND_MOVE_TO 3 // source = Creature, datalog2 = time, x/y/z diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9db420bb2..92249a8b1 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 "9888" + #define REVISION_NR "9889" #endif // __REVISION_NR_H__