[Quest API] Add EVENT_DAMAGE_GIVEN and EVENT_DAMAGE_TAKEN to Perl/Lua. (#2804)

* [Quest API] Add EVENT_DAMAGE_GIVEN and EVENT_DAMAGE_TAKEN to Perl/Lua.

# Perl
- Add `EVENT_DAMAGE_GIVEN`.
- Add `EVENT_DAMAGE_TAKEN`.
- Both events export `$entity_id`, `$damage`, `$spell_id`, `$skill_id`, `$is_damage_shield`, `$is_avoidable`, `$buff_slot`, `$is_buff_tic`, `$special_attack`.

# Lua
- Add `event_damage_given`.
- Add `event_damage_taken`.
- Both events export `e.entity_id`, `e.damage`, `e.spell_id`, `e.skill_id`, `e.is_damage_shield`, `e.is_avoidable`, `e.buff_slot`, `e.is_buff_tic`, `e.special_attack`, and `e.other`.

# Notes
- These events allow operators to have events fire based on damage given or taken, as well as keep better track of a Bot, Client, or NPC's damage per second or otherwise.
- Special Attack is only useful for NPCs, but allows you to see if the attack is Rampage, AERampage, or Chaotic Stab.

* Cleanup.
This commit is contained in:
Alex King 2023-01-29 14:35:17 -05:00 committed by GitHub
parent a489290eba
commit b867d40774
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 257 additions and 14 deletions

View File

@ -3820,6 +3820,98 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
//final damage has been determined.
SetHP(int64(GetHP() - damage));
const auto has_bot_given_event = parse->BotHasQuestSub(EVENT_DAMAGE_GIVEN);
const auto has_bot_taken_event = parse->BotHasQuestSub(EVENT_DAMAGE_TAKEN);
const auto has_npc_given_event = (
(
IsNPC() &&
parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN)
) ||
(
attacker->IsNPC() &&
parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN)
)
);
const auto has_npc_taken_event = (
(
IsNPC() &&
parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN)
) ||
(
attacker->IsNPC() &&
parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN)
)
);
const auto has_player_given_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_GIVEN);
const auto has_player_taken_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_TAKEN);
const auto has_given_event = (
has_bot_given_event ||
has_npc_given_event ||
has_player_given_event
);
const auto has_taken_event = (
has_bot_taken_event ||
has_npc_taken_event ||
has_player_taken_event
);
std::vector<std::any> args;
if (has_taken_event) {
const auto export_string = fmt::format(
"{} {} {} {} {} {} {} {} {}",
attacker ? attacker->GetID() : 0,
damage,
spell_id,
static_cast<int>(skill_used),
FromDamageShield ? 1 : 0,
avoidable ? 1 : 0,
buffslot,
iBuffTic ? 1 : 0,
static_cast<int>(special)
);
if (IsBot() && has_bot_taken_event) {
parse->EventBot(EVENT_DAMAGE_TAKEN, CastToBot(), attacker ? attacker : nullptr, export_string, 0);
} else if (IsClient() && has_player_taken_event) {
args.push_back(attacker ? attacker : nullptr);
parse->EventPlayer(EVENT_DAMAGE_TAKEN, CastToClient(), export_string, 0, &args);
} else if (IsNPC() && has_npc_taken_event) {
parse->EventNPC(EVENT_DAMAGE_TAKEN, CastToNPC(), attacker ? attacker : nullptr, export_string, 0);
}
}
if (has_given_event && attacker) {
const auto export_string = fmt::format(
"{} {} {} {} {} {} {} {} {}",
GetID(),
damage,
spell_id,
static_cast<int>(skill_used),
FromDamageShield ? 1 : 0,
avoidable ? 1 : 0,
buffslot,
iBuffTic ? 1 : 0,
static_cast<int>(special)
);
if (attacker->IsBot() && has_bot_given_event) {
parse->EventBot(EVENT_DAMAGE_GIVEN, attacker->CastToBot(), this, export_string, 0);
} else if (attacker->IsClient() && has_player_given_event) {
args.push_back(this);
parse->EventPlayer(EVENT_DAMAGE_GIVEN, attacker->CastToClient(), export_string, 0, &args);
} else if (attacker->IsNPC() && has_npc_given_event) {
parse->EventNPC(EVENT_DAMAGE_GIVEN, attacker->CastToNPC(), this, export_string, 0);
}
}
if (HasDied()) {
bool IsSaved = false;

View File

@ -171,6 +171,8 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_AUGMENT_REMOVE_CLIENT",
"EVENT_EQUIP_ITEM_BOT",
"EVENT_UNEQUIP_ITEM_BOT",
"EVENT_DAMAGE_GIVEN",
"EVENT_DAMAGE_TAKEN",
// Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT",
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
@ -2031,6 +2033,21 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_DAMAGE_GIVEN:
case EVENT_DAMAGE_TAKEN:{
Seperator sep(data);
ExportVar(package_name.c_str(), "entity_id", sep.arg[0]);
ExportVar(package_name.c_str(), "damage", sep.arg[1]);
ExportVar(package_name.c_str(), "spell_id", sep.arg[2]);
ExportVar(package_name.c_str(), "skill_id", sep.arg[3]);
ExportVar(package_name.c_str(), "is_damage_shield", sep.arg[4]);
ExportVar(package_name.c_str(), "is_avoidable", sep.arg[5]);
ExportVar(package_name.c_str(), "buff_slot", sep.arg[6]);
ExportVar(package_name.c_str(), "is_buff_tic", sep.arg[7]);
ExportVar(package_name.c_str(), "special_attack", sep.arg[8]);
break;
}
default: {
break;
}

View File

@ -116,6 +116,8 @@ typedef enum {
EVENT_AUGMENT_REMOVE_CLIENT,
EVENT_EQUIP_ITEM_BOT,
EVENT_UNEQUIP_ITEM_BOT,
EVENT_DAMAGE_GIVEN,
EVENT_DAMAGE_TAKEN,
// Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT,

View File

@ -158,6 +158,8 @@ const char *LuaEvents[_LargestEventID] = {
"event_augment_remove_client",
"event_equip_item_bot",
"event_unequip_item_bot",
"event_damage_given",
"event_damage_taken"
};
extern Zone *zone;
@ -213,6 +215,8 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone;
NPCArgumentDispatch[EVENT_PAYLOAD] = handle_npc_payload;
NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone;
NPCArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_npc_damage;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
@ -273,6 +277,8 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_BOT_CREATE] = handle_player_bot_create;
PlayerArgumentDispatch[EVENT_AUGMENT_INSERT_CLIENT] = handle_player_augment_insert;
PlayerArgumentDispatch[EVENT_AUGMENT_REMOVE_CLIENT] = handle_player_augment_remove;
PlayerArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_player_damage;
PlayerArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_player_damage;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
@ -312,6 +318,8 @@ LuaParser::LuaParser() {
BotArgumentDispatch[EVENT_PAYLOAD] = handle_bot_payload;
BotArgumentDispatch[EVENT_EQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_UNEQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_bot_damage;
#endif
L = nullptr;

View File

@ -453,6 +453,50 @@ void handle_npc_despawn_zone(
lua_setfield(L, -2, "other");
}
void handle_npc_damage(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushnumber(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "entity_id");
lua_pushnumber(L, std::stoll(sep.arg[1]));
lua_setfield(L, -2, "damage");
lua_pushnumber(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "spell_id");
lua_pushnumber(L, std::stoi(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushboolean(L, std::stoi(sep.arg[4]) == 0 ? false : true);
lua_setfield(L, -2, "is_damage_shield");
lua_pushboolean(L, std::stoi(sep.arg[5]) == 0 ? false : true);
lua_setfield(L, -2, "is_avoidable");
lua_pushnumber(L, std::stoi(sep.arg[6]));
lua_setfield(L, -2, "buff_slot");
lua_pushboolean(L, std::stoi(sep.arg[7]) == 0 ? false : true);
lua_setfield(L, -2, "is_buff_tic");
lua_pushnumber(L, std::stoi(sep.arg[8]));
lua_setfield(L, -2, "special_attack");
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
}
// Player
void handle_player_say(
QuestInterface *parse,
@ -1168,6 +1212,51 @@ void handle_player_bot_create(
lua_setfield(L, -2, "bot_gender");
}
void handle_player_damage(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushnumber(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "entity_id");
lua_pushnumber(L, std::stoll(sep.arg[1]));
lua_setfield(L, -2, "damage");
lua_pushnumber(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "spell_id");
lua_pushnumber(L, std::stoi(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushboolean(L, std::stoi(sep.arg[4]) == 0 ? false : true);
lua_setfield(L, -2, "is_damage_shield");
lua_pushboolean(L, std::stoi(sep.arg[5]) == 0 ? false : true);
lua_setfield(L, -2, "is_avoidable");
lua_pushnumber(L, std::stoi(sep.arg[6]));
lua_setfield(L, -2, "buff_slot");
lua_pushboolean(L, std::stoi(sep.arg[7]) == 0 ? false : true);
lua_setfield(L, -2, "is_buff_tic");
lua_pushnumber(L, std::stoi(sep.arg[8]));
lua_setfield(L, -2, "special_attack");
if (extra_pointers && extra_pointers->size() >= 1) {
Lua_Mob l_mob(std::any_cast<Mob*>(extra_pointers->at(1)));
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
}
}
// Item
void handle_item_click(
QuestInterface *parse,
@ -1977,7 +2066,7 @@ void handle_bot_equip_item(
lua_setfield(L, -2, "item");
}
void handle_bot_unequip_item(
void handle_bot_damage(
QuestInterface *parse,
lua_State* L,
Bot* bot,
@ -1986,22 +2075,39 @@ void handle_bot_unequip_item(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushnumber(L, extra_data);
lua_setfield(L, -2, "item_id");
Seperator sep(data.c_str());
lua_pushnumber(L, std::stoi(sep.arg[0]));
lua_setfield(L, -2, "item_quantity");
lua_pushnumber(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "entity_id");
lua_pushnumber(L, std::stoi(sep.arg[1]));
lua_setfield(L, -2, "slot_id");
lua_pushnumber(L, std::stoll(sep.arg[1]));
lua_setfield(L, -2, "damage");
Lua_ItemInst l_item(extra_data);
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
lua_pushnumber(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "spell_id");
lua_pushnumber(L, std::stoi(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushboolean(L, std::stoi(sep.arg[4]) == 0 ? false : true);
lua_setfield(L, -2, "is_damage_shield");
lua_pushboolean(L, std::stoi(sep.arg[5]) == 0 ? false : true);
lua_setfield(L, -2, "is_avoidable");
lua_pushnumber(L, std::stoi(sep.arg[6]));
lua_setfield(L, -2, "buff_slot");
lua_pushboolean(L, std::stoi(sep.arg[7]) == 0 ? false : true);
lua_setfield(L, -2, "is_buff_tic");
lua_pushnumber(L, std::stoi(sep.arg[8]));
lua_setfield(L, -2, "special_attack");
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
}
#endif

View File

@ -210,6 +210,16 @@ void handle_npc_despawn_zone(
std::vector<std::any> *extra_pointers
);
void handle_npc_damage(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Player
void handle_player_say(
QuestInterface *parse,
@ -652,6 +662,14 @@ void handle_player_augment_remove(
std::vector<std::any> *extra_pointers
);
void handle_player_damage(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Item
void handle_item_click(
@ -965,7 +983,7 @@ void handle_bot_equip_item(
std::vector<std::any> *extra_pointers
);
void handle_bot_unequip_item(
void handle_bot_damage(
QuestInterface *parse,
lua_State* L,
Bot* bot,