[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 <nofantasy@nf.no>
This commit is contained in:
NoFantasy 2010-05-13 16:38:15 +02:00
parent 0344a8e838
commit 31ec245b68
4 changed files with 81 additions and 22 deletions

View file

@ -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<WorldObject*>(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<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> 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

View file

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

View file

@ -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

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "9888"
#define REVISION_NR "9889"
#endif // __REVISION_NR_H__