Damage Revamp

EQ2Emulator Development forum.

Moderator: Team Members

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Damage Revamp

Post by thefoof » Thu Jul 25, 2013 6:35 pm

Been working on our damage formulas and needed somewhere to post my changes and discuss formulas with folks so here it is :D.

Just committed some new code, I implemented DPS mod damage for auto attacks. The UI tells you how much dps you have but not the percentage of the mod so I'll have to try and identify that element later. But the damage is calculated correctly. Here's the formula for anybody whos curious:

dps = Entity's DPS
DPS 1-100 -> dps / 100
DPS 101-200-> ((dps - 100) * .25 + 100) / 100
DPS 201-300-> ((dps - 200) * .1 + 125) / 100
DPS 301-900-> ((dps - 300) * .05 + 135) / 100
DPS 901 + -> ((dps - 900) * .01 + 165) / 100


and then multiply damage by (DPS multiplier + 1).

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: Damage Revamp

Post by Jabantiz » Thu Jul 25, 2013 6:45 pm

There are links to various equations in this post, they may or may not be useful for you. Most are for max level and above the stat cap though, finding info for below max level and below the stat caps is near to impossible so I left what we had in there. I hope some of those links will be helpful.

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Re: Damage Revamp

Post by thefoof » Thu Jul 25, 2013 7:10 pm

Thanks, that link should help.

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Primary Stats

Post by thefoof » Fri Jul 26, 2013 11:16 pm

Just a collective reference for later: Damage bonus from primary stats hits the first "soft cap" at roughly 800 of that stat. Which is a 52% bonus (roughly). Things then flatten out dramatically until you reach 1200 of that stat, where you receive (roughly) a 65% bonus, which is where the second "soft cap" takes effect, and you gain more per point.

The formula for the > 1200 curve can be shown as roughly B = [0.8*log(S/1200)/log(1.02)] + 66.41 (formula from flames, S is the stat B is the bonus percentage).

Less than 1200 formula is something that we'll more than likely have to figure out, I think there weren't many efforts to find it because when people were in that range, the bonuses were pretty much crap past 800.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Damage Revamp

Post by John Adams » Sat Jul 27, 2013 12:21 am

~drools on himself~

wha?


(nice, sounds like we know what we're doing finally!)

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Re: Damage Revamp

Post by thefoof » Sun Jul 28, 2013 1:40 am

I don't understand logarithms but the good news is c++ compilers do :mrgreen:

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Healing Spells

Post by thefoof » Mon Jul 29, 2013 5:26 pm

I notice that currently we handle healing spells by lua script using the ModifyHP() function running the calculations in the script, we will eventually either need to change this to another damage function for heals or create a new lua function to handle this, because 1) the healing packet doesn't get sent for combat chat 2)potency and other modifiers don't do anything.

Any thoughts on how we want to do this?

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: Damage Revamp

Post by Jabantiz » Mon Jul 29, 2013 6:03 pm

Code: Select all

int EQ2Emu_lua_SpellHeal(lua_State* state){
	if(!lua_interface)
		return 0;

	LogWrite(MISC__TODO, 1, "TODO", " implement\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);

	/*Spawn* target = lua_interface->GetSpawn(state);
	Spawn* caster = lua_interface->GetCurrentSpell()->caster;
	int32 amount =  lua_interface->GetInt32Value(state, 2);*/

	return 0;
}
We already have a lua function just need to add the required code, could add the potency and other mods in this function.

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Re: Damage Revamp

Post by thefoof » Mon Jul 29, 2013 6:05 pm

Nice thanks, I'll look into it.

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Re: Healing Spells

Post by thefoof » Mon Jul 29, 2013 10:01 pm

Here's what I came up with for the lua function basically a copy and paste of SpellAttack.

Code: Select all

int EQ2Emu_lua_SpellHeal(lua_State* state){
	if(!lua_interface)
		return 0;
	Spawn* target = lua_interface->GetSpawn(state);
	LuaSpell* luaspell = lua_interface->GetCurrentSpell(state);
	if(!luaspell)
		return 0;
	Spawn* caster = luaspell->caster;
	sint32 type = 0; //HEAL_PACKET_TYPE_SIMPLE_HEAL? have to figure out heal packet types
	sint32 heal_type = lua_interface->GetInt32Value(state, 2);//ward heal ect
	int32 min_heal = lua_interface->GetInt32Value(state, 3);
	int32 max_heal = lua_interface->GetInt32Value(state, 4);	
	lua_interface->ResetFunctionStack(state);
	if(caster && caster->IsEntity()){
		bool success = false;
		luaspell->resisted = false;
		if (luaspell->targets.size() > 0) {
			for (int32 i = 0; i < luaspell->targets.size(); i++) {
				if (luaspell->targets[i]) {
					float distance = caster->GetDistance(luaspell->targets[i], true);
					distance -= caster->appearance.pos.collision_radius/10;
					distance -= luaspell->targets[i]->appearance.pos.collision_radius/10;
					((Entity*)caster)->SpellHeal(luaspell->targets[i], distance, luaspell, type, heal_type, min_heal, max_heal);
				}
			}
			success = true;
		}
		else if (target) {
			float distance = caster->GetDistance(target, true);
			distance -= caster->appearance.pos.collision_radius/10;
			distance -= target->appearance.pos.collision_radius/10;
			if (((Entity*)caster)->SpellHeal(target, distance, luaspell, type, 0, min_heal, max_heal))
				success = true;
		}
		if (success) {
			Spell* spell = luaspell->spell;
			if(caster->GetZone())
				caster->GetZone()->TriggerCharSheetTimer();
		}
	}
	return 0;
}
And here's SpellHeal in the combat code

Code: Select all

bool Entity::SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, int8 type, int8 damage_type, int32 low_heal, int32 high_heal){
	 if(!target || !luaspell || !luaspell->spell || distance > luaspell->spell->GetSpellData()->range || IsMezzedOrStunned() || IsStifled())
		return false;

	 /*Spell* spell = luaspell->spell;
	 Skill* skill = 0;
	 skill = master_skill_list.GetSkill(spell->GetSpellData()->mastery_skill;*/
	 int32 heal_amt = 0;

	 if(low_heal > high_heal)
		heal_amt = low_heal;
	if(low_heal == high_heal)
		heal_amt = low_heal;
	else
		heal_amt = MakeRandomInt(low_heal, high_heal);

	if (heal_amt > 0){
		//int32 base_roll = heal_amt;
		//potency mod
		heal_amt += (heal_amt * (stats[ITEM_STAT_POTENCY] / 100 + 1));

		//primary stat mod, insert forula here when done
		//heal_amt += base_roll * (GetPrimaryStat()
		
		//Ability Modifier can only be up to half of base roll + potency and primary stat bonus
		heal_amt += (int32)min(info_struct.ability_modifier, (float)(heal_amt / 2));
	}
	else
		return false;

	// Crit Roll
	float chance = max((float)0, info_struct.crit_chance);
	if (MakeRandomFloat(0, 100) <= chance) {
		//Apply total crit multiplier with crit bonus
		heal_amt *= info_struct.crit_bonus / 100 + 1.3;

		/* Change packet type to crit
		if (type == DAMAGE_PACKET_TYPE_SIMPLE_DAMAGE)
			type = DAMAGE_PACKET_TYPE_SIMPLE_CRIT_DMG;
		else if (type == DAMAGE_PACKET_TYPE_SPELL_DAMAGE)
			type = DAMAGE_PACKET_TYPE_SPELL_CRIT_DMG;*/
	}

	if (target->GetHP() + heal_amt > target->GetTotalHP())
			target->SetHP(target->GetTotalHP());
	else
		target->SetHP(target->GetHP() + heal_amt);
	target->GetZone()->TriggerCharSheetTimer();
	return true;
}
Have to figure out the heal packet format before I can get heals to show up in the combat window (I assume the heal numbers show up too). Not going to commit until jab checks it out as I don't understand all of the spell code :P

Syntax is SpellHeal(Target, HealType, MinHeal, MaxHeal)

Obviously healtypes aren't defined yet so it's not really used for now, will be for wards ect eventually. The type variables should eventually be crit heal, normal heal ect.

Side note once heal packets are finished should look at a separate function for taunts and threat packets as well. Almost thinking we should have different damage functions for (Auto attack, taunts, heals, spell attacks), for the sake of performance and simplicity reading the code. Since we call them from different functions anyway.

Jabantiz
Lead Developer
Posts: 2912
Joined: Wed Jul 25, 2007 2:52 pm
Location: California

Re: Damage Revamp

Post by Jabantiz » Mon Jul 29, 2013 11:13 pm

I haven't tested the code but reading over it, it all looks good. If it works on your local tests then I say go ahead and commit it.
Side note once heal packets are finished should look at a separate function for taunts and threat packets as well. Almost thinking we should have different damage functions for (Auto attack, taunts, heals, spell attacks), for the sake of performance and simplicity reading the code. Since we call them from different functions anyway.
Taunts already call a separate function, both lua and code, however the special taunt packets haven't been added into the code yet.

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Re: Healing Spells

Post by thefoof » Tue Jul 30, 2013 2:16 am

Okay so I made an lua function to test out some different values after I thought I found a good struct, I figured out the packets have the elements caster, target, spellname, and type. Here's what the following types do:

type 5 and 0 = heal
type 4, 6 and 7= absorb regen
type 1 = crit heal
type 2 and 3 = ward
type 8 = mana
type 9 = crit mana
type 80 = savagery

Will commit my struct in a minute.

EDIT: each type seems to have multiple values that it can be, so there are other probably types I haven't found yet and some different values for the types I do have, I plan on just using the lowest value available for each type though.

User avatar
thefoof
Retired
Posts: 630
Joined: Wed Nov 07, 2012 7:36 pm
Location: Florida

Re: Healing Spells

Post by thefoof » Tue Jul 30, 2013 10:53 pm

I just finished up the framework for healing packets and heal amount calcs, the new syntax for the function is SpellHeal(Target, "HealType", MinHeal, MaxHeal)

Where HealType is a string value such as "Power", "Heal" or "Ward", MinHeal is the minimum amount healed and MaxHeal is the max.

You can use multiple SpellHeal functions if a spell gives more than one type.

Will document the function in detail tomorrow. (Testers keep in mind until we get new spell data and write new scripts heal numbers won't show up :P)

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Healing Spells

Post by John Adams » Wed Jul 31, 2013 8:11 am

thefoof wrote:(Testers keep in mind until we get new spell data and write new scripts heal numbers won't show up :P)
I am almost done with my Spell spawning scripting, so hopefully this weekend I can start pooping out new spells data that automatically gets updated from the data.soe.com API.

User avatar
John Adams
Retired
Posts: 9684
Joined: Thu Jul 26, 2007 6:27 am
EQ2Emu Server: EQ2Emulator Test Center
Characters: John
Location: Arizona
Contact:

Re: Damage Revamp

Post by John Adams » Thu Aug 08, 2013 10:16 am

btw, Foof and Jab... when you are implementing code, especially calcs, please try and envision how the Rules system can be implemented to make those calculations customizable. Eg., from Foof's code:

Code: Select all

float Entity::CalculateDPSMultiplier(){
	float dps = GetInfoStruct()->dps;
	if (dps <= 100)
		return dps / 100;
	else if (dps <= 200)
		return ((dps - 100) * .25 + 100) / 100;
	else if (dps <= 300)
		return ((dps - 200) * .1 + 125) / 100;
	else if (dps <= 900)
		return ((dps - 300) * .05 + 135) / 100;
	else
		return ((dps - 900) * .01 + 165) / 100;
}
Curious if nearly all these #'s can be Rules, so my server can handle DPS differently than your server?

If we can make these considerations while implementing new code, it will save time later having to re-discover places where Rules will offer more server customization.

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests