LUA SpawnSet and SpellHeal updates

SpawnSet(NPC, "skin_color", "255 0 0", false, true)

skin_color takes in 3 arguments as a string, R G B
two new parameters after value:
- no_update, when set to true (default false, its an inverse flag of send_update) we will not send update of spawn changes
- temporary_flag, when set to true database is not update (default false again to keep compat with LUA scripts).

SpellHeal(Spawn, "heal", min, max, NPC, 0, 0, "New Spell Name")
This commit is contained in:
image 2020-09-04 07:31:07 -04:00
parent 409a8d78c4
commit 81aa1f23e3
7 changed files with 60 additions and 14 deletions

View file

@ -545,7 +545,7 @@ bool Entity::ProcAttack(Spawn* victim, int8 damage_type, int32 low_damage, int32
return true;
}
bool Entity::SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string heal_type, int32 low_heal, int32 high_heal, int8 crit_mod, bool no_calcs){
bool Entity::SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string heal_type, int32 low_heal, int32 high_heal, int8 crit_mod, bool no_calcs, string custom_spell_name){
if(!target || !luaspell || !luaspell->spell)
return false;
@ -673,7 +673,7 @@ bool Entity::SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string
target->GetZone()->TriggerCharSheetTimer();
if (heal_amt > 0)
GetZone()->SendHealPacket(this, target, type, heal_amt, luaspell->spell->GetName());
GetZone()->SendHealPacket(this, target, type, heal_amt, custom_spell_name.length() > 0 ? (char*)custom_spell_name.c_str() : luaspell->spell->GetName());
CheckProcs(PROC_TYPE_HEALING, target);
CheckProcs(PROC_TYPE_BENEFICIAL, target);

View file

@ -154,6 +154,7 @@ Commands::Commands(){
spawn_set_values["holiday_flag"] = SPAWN_SET_VALUE_HOLIDAY_FLAG;
spawn_set_values["merchant_min_level"] = SPAWN_SET_VALUE_MERCHANT_MIN_LEVEL;
spawn_set_values["merchant_max_level"] = SPAWN_SET_VALUE_MERCHANT_MAX_LEVEL;
spawn_set_values["skin_color"] = SPAWN_SET_SKIN_COLOR;
zone_set_values["expansion_id"] = ZONE_SET_VALUE_EXPANSION_ID;
zone_set_values["name"] = ZONE_SET_VALUE_NAME;
@ -197,7 +198,9 @@ bool Commands::SetSpawnCommand(Client* client, Spawn* target, int8 type, const c
return false;
int32 val = 0;
try{
if(type != SPAWN_SET_VALUE_NAME && !(type >= SPAWN_SET_VALUE_SPAWN_SCRIPT && type <= SPAWN_SET_VALUE_SUB_TITLE) && !(type >= SPAWN_SET_VALUE_PREFIX && type <= SPAWN_SET_VALUE_EXPANSION_FLAG || type == SPAWN_SET_VALUE_HOLIDAY_FLAG))
if(type != SPAWN_SET_VALUE_NAME &&
!(type >= SPAWN_SET_VALUE_SPAWN_SCRIPT && type <= SPAWN_SET_VALUE_SUB_TITLE) && !(type >= SPAWN_SET_VALUE_PREFIX && type <= SPAWN_SET_VALUE_EXPANSION_FLAG || type == SPAWN_SET_VALUE_HOLIDAY_FLAG)
&& type != SPAWN_SET_SKIN_COLOR)
val = atoul(value);
}
catch(...){
@ -205,7 +208,7 @@ bool Commands::SetSpawnCommand(Client* client, Spawn* target, int8 type, const c
client->Message(CHANNEL_COLOR_RED, "Invalid numeric spawn value: %s", value);
return false;
}
if(temporary && temp_value){
if(temporary){
char tmp[128] = {0};
switch(type){
case SPAWN_SET_VALUE_NAME:{
@ -500,8 +503,26 @@ bool Commands::SetSpawnCommand(Client* client, Spawn* target, int8 type, const c
target->SetMerchantLevelRange(target->GetMerchantMinLevel(), atoul(value));
break;
}
case SPAWN_SET_SKIN_COLOR: {
if (target->IsNPC())
{
Seperator* skinsep = new Seperator(value, ' ', 3, 500, true);
if (skinsep->IsNumber(0) && skinsep->IsNumber(1) && skinsep->IsNumber(2))
{
EQ2_Color clr;
clr.red = atoul(skinsep->arg[0]);
clr.green = atoul(skinsep->arg[1]);
clr.blue = atoul(skinsep->arg[2]);
*temp_value = string(tmp);
((Entity*)target)->SetSkinColor(clr);
}
safe_delete(skinsep);
}
break;
}
if(temp_value)
*temp_value = string(tmp);
}
}
else{
@ -838,7 +859,28 @@ bool Commands::SetSpawnCommand(Client* client, Spawn* target, int8 type, const c
else
target->SetSpawnScript(value);
break;
}
}
case SPAWN_SET_SKIN_COLOR: {
if (target->IsNPC())
{
Seperator* skinsep = new Seperator(value, ' ', 3, 500, true);
if (skinsep->IsNumber(0) && skinsep->IsNumber(1) && skinsep->IsNumber(2))
{
EQ2_Color clr;
clr.red = atoul(skinsep->arg[0]);
clr.green = atoul(skinsep->arg[1]);
clr.blue = atoul(skinsep->arg[2]);
((Entity*)target)->SetSkinColor(clr);
Query replaceSkinQuery;
replaceSkinQuery.AddQueryAsync(0, &database, Q_DELETE, "delete from npc_appearance where spawn_id=%u and type='skin_color'", target->GetDatabaseID());
replaceSkinQuery.AddQueryAsync(0, &database, Q_DELETE, "insert into npc_appearance set spawn_id=%u, type='skin_color', red=%u, green=%u, blue=%u", target->GetDatabaseID(), clr.red, clr.green, clr.blue);
}
safe_delete(skinsep);
}
break;
}
}
}
return true;
@ -3649,7 +3691,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
else
{
string name = string(spawn->GetName());
if(SetSpawnCommand(client, spawn, set_type, sep->arg[1]))
if(SetSpawnCommand(client, spawn, set_type, sep->argplus[1]))
{
if (set_type == SPAWN_SET_VALUE_EXPANSION_FLAG || set_type == SPAWN_SET_VALUE_HOLIDAY_FLAG)
{
@ -3680,7 +3722,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
}
default:
{
client->GetCurrentZone()->ApplySetSpawnCommand(client, spawn, set_type, sep->arg[1]);
client->GetCurrentZone()->ApplySetSpawnCommand(client, spawn, set_type, sep->argplus[1]);
break;
}
}

View file

@ -555,6 +555,7 @@ private:
#define SPAWN_SET_VALUE_MERCHANT_MIN_LEVEL 60
#define SPAWN_SET_VALUE_MERCHANT_MAX_LEVEL 61
#define SPAWN_SET_VALUE_HOLIDAY_FLAG 62
#define SPAWN_SET_SKIN_COLOR 63
#define ZONE_SET_VALUE_EXPANSION_ID 0
#define ZONE_SET_VALUE_NAME 1

View file

@ -472,7 +472,7 @@ public:
void RangeAttack(Spawn* victim, float distance, Item* weapon, Item* ammo, bool multi_attack = false);
bool SpellAttack(Spawn* victim, float distance, LuaSpell* luaspell, int8 damage_type, int32 low_damage, int32 high_damage, int8 crit_mod = 0, bool no_calcs = false);
bool ProcAttack(Spawn* victim, int8 damage_type, int32 low_damage, int32 high_damage, string name, string success_msg, string effect_msg);
bool SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string heal_type, int32 low_heal, int32 high_heal, int8 crit_mod = 0, bool no_calcs = false);
bool SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string heal_type, int32 low_heal, int32 high_heal, int8 crit_mod = 0, bool no_calcs = false, string custom_spell_name="");
int8 DetermineHit(Spawn* victim, int8 damage_type, float ToHitBonus, bool spell);
float GetDamageTypeResistPercentage(int8 damage_type);
Skill* GetSkillByWeaponType(int8 type, bool update);

View file

@ -236,9 +236,11 @@ int EQ2Emu_lua_SpawnSet(lua_State* state) {
Spawn* spawn = lua_interface->GetSpawn(state);
string variable = lua_interface->GetStringValue(state, 2);
string value = lua_interface->GetStringValue(state, 3);
bool no_update = lua_interface->GetBooleanValue(state, 4); // send update is true by default in SetSpawnCommand, so allow user to specify 'true' to disable send update.
bool temporary_flag = lua_interface->GetBooleanValue(state, 5); // default false as originally designed, allow user to set temporary_flag true to not update DB
int32 type = commands.GetSpawnSetType(variable);
if (type != 0xFFFFFFFF && value.length() > 0 && spawn)
commands.SetSpawnCommand(0, spawn, type, value.c_str());
commands.SetSpawnCommand(0, spawn, type, value.c_str(), !no_update, temporary_flag);
return 0;
}
@ -895,13 +897,14 @@ int EQ2Emu_lua_SpellHeal(lua_State* state) {
Spawn* target = lua_interface->GetSpawn(state, 4);
int8 crit_mod = lua_interface->GetInt32Value(state, 5);
bool no_calcs = lua_interface->GetInt32Value(state, 6) == 1;
string custom_spell_name = lua_interface->GetStringValue(state, 7);//custom spell name
lua_interface->ResetFunctionStack(state);
if (caster && caster->IsEntity()) {
bool success = false;
luaspell->resisted = false;
if (target) {
float distance = caster->GetDistance(target, true);
if (((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs))
if (((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs, custom_spell_name))
success = true;
}
if (luaspell->targets.size() > 0) {
@ -911,7 +914,7 @@ int EQ2Emu_lua_SpellHeal(lua_State* state) {
for (int32 i = 0; i < luaspell->targets.size(); i++) {
if ((target = zone->GetSpawnByID(luaspell->targets[i]))) {
float distance = caster->GetDistance(target, true);
((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs);
((Entity*)caster)->SpellHeal(target, distance, luaspell, heal_type, min_heal, max_heal, crit_mod, no_calcs, custom_spell_name);
}
}
luaspell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);

View file

@ -3708,7 +3708,7 @@ void ZoneServer::SetSpawnCommand(int32 spawn_id, int8 type, char* value, Client*
LogWrite(MISC__TODO, 1, "TODO", "%s does nothing!\n%s, %i", __FUNCTION__, __FILE__, __LINE__);
}
void ZoneServer::ApplySetSpawnCommand(Client* client, Spawn* target, int8 type, char* value){
void ZoneServer::ApplySetSpawnCommand(Client* client, Spawn* target, int8 type, const char* value){
// This will apply the /spawn set command to all the spawns in the zone with the same DB ID, we do not want to set
// location values (x, y, z, heading, grid) for all spawns in the zone with the same DB ID, only the targeted spawn
if(type == SPAWN_SET_VALUE_SPAWNENTRY_SCRIPT || type == SPAWN_SET_VALUE_SPAWNLOCATION_SCRIPT || (type >= SPAWN_SET_VALUE_X && type <= SPAWN_SET_VALUE_LOCATION) ||

View file

@ -258,7 +258,7 @@ public:
int16 SetSpawnTargetable(Spawn* spawn, float distance);
int16 SetSpawnTargetable(int32 spawn_id);
void ApplySetSpawnCommand(Client* client, Spawn* target, int8 type, char* value);
void ApplySetSpawnCommand(Client* client, Spawn* target, int8 type, const char* value);
void SetSpawnCommand(Spawn* spawn, int8 type, char* value, Client* client = 0);
void SetSpawnCommand(int32 spawn_id, int8 type, char* value, Client* client = 0);
void AddLoot(NPC* npc);