Median 2008: Retaliate, Crucify, and other "when hit" skill mechanics

Weekly updated column for helping skill development. Users can't directly post requests but a PM or mail can be sent to Skill-Clinician.

Moderator: Skill Clinician

Post Reply
User avatar
mmpx222
Junior Member
Paladin
Posts: 154
Joined: Sat Apr 26, 2014 9:19 am
Korea South

Median 2008: Retaliate, Crucify, and other "when hit" skill mechanics

Post by mmpx222 » Tue Jan 15, 2019 9:47 am

Disclaimer

For years, I wondered how the interesting skills in Median worked. I finally got around to dissecting Median, and would like to share the results. I duly give credit to Brother Laz for his amazing work. Same goes to Joel and all others who worked on Median.

Median 2008 v157b seems to be the last version that still contains the source TXT files. Later versions provide only compiled BIN files and dummy TXT files (to prevent hacking and/or plagiarism). This means I'm forced to examine old solutions to problems that may be solved with new, better modding techniques. However, given the long history of the mod, I doubt there are many new tricks that Brother Laz didn't know at that time.

Retaliate, Retribute, Cherub Strike

Several skills in Median require you to be attacked by a monster to do something. For example, Retaliate spawns weapon damage novas on each melee attack, but only when you are attacked by a monster. Retaliate is a Charged Strike clone that spawns a melee nova (a technique that Brother Laz mentioned once) combined with a hit-skill on monsters that applies a stat to the player.

To elaborate, this is accomplished by using a dummy stat (event_hit2) that will be applied to the player:

Code: Select all

[421]
Stat=event_hit2
ID=420
* Laz / comments=technical - not suited for affixes
Signed=1
Send Bits=12
Divide=1024
*eol=0
This stat is applied by the Mon Hit Monster Effect curse (skill id=483):

Code: Select all

[484]
skill=Mon Hit Monster Effect
Id=483
* Laz / status=responsible for when-struck state
srvdofunc=30
aurafilter=FindPlayers | FindMonsters
auratargetstate=justbeenhit
auralencalc=50+stat('skill_holyinsanity_effect'.accr)
aurarangecalc=2
aurastat1=event_hit2
aurastatcalc1=1
aurastat2=passive_fire_mastery
aurastatcalc2=stat('skill_hex_effect'.accr)
aurastat3=passive_ltng_mastery
aurastatcalc3=stat('skill_hex_effect'.accr)
aurastat4=passive_cold_mastery
aurastatcalc4=stat('skill_hex_effect'.accr)
aurastat5=passive_pois_mastery
aurastatcalc5=stat('skill_hex_effect'.accr)
aurastat6=damagepercent
aurastatcalc6=stat('passive_hex_adddmg'.accr)
cltstfunc=18
cltdofunc=30
(rest omitted for brevity)
I'll get to the skill_hex_effect part later. The justbeenhit state uses the Inner Sight overlay (/data/global/overlays/HardenArmor.dcc), but that isn't important.

The curse added as a 100% Chance to Cast on Strike (hit-skill) on every monster using MonProp.txt:

Code: Select all

[19]
Id=othernophysimmune
prop1=hit-skill
par1=483
min1=100
max1=1
prop2=death-skill
par2=484
min2=100
max2=1
prop3=aura
par3=574
min3=1
max3=1

(similar values for Nightmare and Hell props)
Many rows in MonProp.txt use hit-skill with par2=483. Now, monsters will briefly apply event_hit2 when they hit the player.

Let's look at Retaliate:

Code: Select all

[427]
skill=Retaliate
Id=426
charclass=pal
skilldesc=retaliate
* Laz / status=melee holy
srvstfunc=6
srvdofunc=11
srvmissilea=retaliatespawner
srvmissileb=retaliatespawner
srvmissilec=retaliatespawner
cltdofunc=19
cltmissilea=retaliatespawner
cltmissileb=retaliatespawner
cltmissilec=retaliatespawner
enhanceable=1
attackrank=5
range=h2h
itypea1=mele
anim=A1
seqtrans=A1
monanim=A1
UseAttackRate=1
TargetableOnly=1
SearchEnemyXY=1
AttackNoMana=1
skpoints=((skill('Arcane Strike'.blvl)+skill('Superbeast'.blvl)+skill('Blood Flash'.blvl))==0)?(((ulvl)<((blvl-1-stat('skill_more'.accr))*6))?(stat('newskills'.accr)+1):1):(stat('newskills'.accr)+1)
reqlevel=1
maxlvl=99
restrict=1
delay=(blvl > 0) ? 0 : ((lvl > 0) ? 50 : 0)
leftskill=1
minmana=0
manashift=8
mana=3
lvlmana=3
interrupt=1
calc1=(stat('event_hit2'.accr) > 0 ? 1 : 0)
*calc1 desc=spawn shockwave ?
InGame=1
HitShift=8
SrcDam=224
cost add=0
This is a clone of cLoD Charged Strike. It uses calc1 (# of missiles) to spawn 1 missile (retaliatespawner) only if the character has event_hit2 (i.e. has been recently hit by a monster).

In Missiles.txt, retaliatespawner looks like this:

Code: Select all


[987]
Missile=retaliatespawner
Id=986
pCltDoFunc=1
pCltHitFunc=30
pSrvDoFunc=1
pSrvHitFunc=29
{filtered}=1
*server hit param1 desc=increment
cHitPar1=1
*client hit param1 desc=increment
Range=1
Red=255
Green=255
Blue=255
InitSteps=1
Activate=0
LoopAnim=2
CelFile=null
animrate=1024
AnimLen=2
AnimSpeed=16
LastCollide=1
ClientCol=1
Size=1
AlwaysExplode=1
Trans=1
ResultFlags=4
HitShift=8
NumDirections=1
HitSubMissile1=retaliatenova
CltHitSubMissile1=retaliatenova
EOL=0
This missile is invisible (CelFile=null), immediately explodes (Range=1), always explodes (AlwaysExplode=1), and uses the frozenorb hit functions (30/29) to spawn 64 submissiles (retaliatenova) in a circle. retaliatenova is a fairly basic missile that carries 3/4 of weapon damage.

Retribute is very similar, except that the nova missiles use battlecry server hit function (pSrvHitFunc=21) to apply a debuff to enemies instead of damaging them.

Cherub Strike is another similar skill. The main missile (deathrockcenter) is stationary, lasts ~4 seconds, and uses the frozenorb move functions (19/15) to spawn a submissile (deathrockdelay) in a random† direction every 10 frames. deathrockdelay immedately explodes, and uses the lightningfury hit functions (25/20) to spawn homing submissiles (deathrockbolt) that carry 3/4 weapon damage.

† We know the direction is not actually random, but is incremented by a fixed value.

Crucify, Black Lotus Strike, Death Blossom, Overpower

These skills are also Charged Strike clones, but do the opposite: They spawn a missile only if you were not recently hit by a monster. All of them use the following formula:

Code: Select all

calc1=(stat('event_hit2'.accr) == 0 ? 1 : 0)
Which means "spawn 1 missile if I don't have the event_hit2 stat".

Crucify also does some fancy missile tricks. The initial missile (finalstrikespawner) also uses frozenorb hit functions to spawn 8 submissiles (finalstrikenova), which use the lightningfury hit functions to spawn the actual homing, damaging missiles (finalspike).

Black Lotus Strike and Death Blossom missiles are fairly basic variations on Frozen Orb explosions (# of nova missiles, nova size, etc.).

Overpower is a bit more interesting. The main missile (overpowercenter) is stationary, lasts a couple of seconds, and uses the frozenorb move functions to spawn submissiles (overpowerdelay) every frame. Each overpowerdelay lasts 1 frame and spawns 64 submissiles (overpowernova), which carry 1/4 weapon damage and apply a NextDelay of 4.

Holy Insanity

Holy Insanity is a curse that applies the skill_holyinsanity_effect stat to the enemy:

Code: Select all

[428]
skill=Holy Insanity
Id=427
charclass=pal
skilldesc=holyinsanity
* Laz / status=melee holy
srvdofunc=30
aurafilter=FindPlayers | FindMonsters
auratargetstate=holyinsanity
auralencalc=(ln34*(100+stat('profession_duration_mod'.accr)))/100
aurarangecalc=par5
aurastat1=skill_holyinsanity_effect
aurastatcalc1=ln12+skill('Lionheart'.blvl)*par4
aurastat2=passive_hex_adddmg
aurastatcalc2=ln78
stsound=necromancer_curse_cast
castoverlay=suncast
enhanceable=1
attackrank=3
range=none
anim=SC
seqtrans=SC
monanim=xx
LineOfSight=4
ItemEffect=1
ItemCastSound=necromancer_curse_cast
skpoints=((ulvl-6)<((blvl-1-stat('skill_more'.accr))*6))?(stat('newskills'.accr)+1):1
reqlevel=6
maxlvl=99
reqskill1=Retaliate
minmana=0
manashift=8
mana=14
lvlmana=7
interrupt=1
Param1=35
*Param1 Description=duration bonus
Param2=18
*Param2 Description=duration bonus per level
Param3=325
*Param3 Description=duration
Param4=5
*Param4 Description=effect synergy
Param5=15
*Param5 Description=radius
Param7=0
*Param7 Description=dmg % when struck
Param8=0
*Param8 Description=dmg % when struck per level
InGame=1
HitShift=8
cost add=0
It also applies passive_hex_adddmg of zero for some reason. Maybe Laz left it there after testing balance stuff?

Looking back at Mon Hit Monster Effect, we see:

Code: Select all

auralencalc=50+stat('skill_holyinsanity_effect'.accr)
...which increases the duration of the justbeenhit state. This makes the event_hit2 stat persist longer, allowing Retaliate and its siblings to spawn missiles longer. This also allows the Paladin to invest in some defense without hurting his damage output. On the other hand, Holy Insanity will also disable Assassin skills for a longer time.

Hex

Hex is another curse that applies the skill_hex_effect and passive_hex_adddmg stats:

Code: Select all

[469]
skill=Hex
Id=468
charclass=sor
skilldesc=hex
* Laz / status=magic
srvdofunc=30
aurafilter=FindPlayers | FindMonsters
auratargetstate=hexed
auralencalc=(par8*(100+stat('profession_duration_mod'.accr)))/100
aurarangecalc=dm56
aurastat1=skill_hex_effect
aurastatcalc1=dm12
aurastat2=passive_hex_adddmg
aurastatcalc2=stat('passive_hex_adddmg'.accr)+(skill('Mana Sweep'.blvl)*par7)
aurastat3=skill_holyinsanity_effect
aurastatcalc3=ln34
stsound=necromancer_curse_cast
cltstfunc=18
cltdofunc=30
cltmissilea=curseamplifydamage
cltmissilec=cursecast
enhanceable=1
attackrank=3
range=none
anim=SC
seqtrans=SC
monanim=xx
LineOfSight=4
ItemEffect=1
ItemCastSound=necromancer_curse_cast
skpoints=((ulvl-12)<((blvl-1-stat('skill_more'.accr))*6))?(stat('newskills'.accr)+1):1
reqlevel=12
maxlvl=99
reqskill1=Moonstrike
minmana=0
manashift=8
mana=48
lvlmana=16
interrupt=1
Param1=50
*Param1 Description=dmg % elem min
Param2=400
*Param2 Description=dmg % elem max
Param3=0
*Param3 Description=duration bonus
Param4=5
*Param4 Description=duration bonus per level
Param5=0
*Param5 Description=radius min
Param6=40
*Param6 Description=radius max
Param7=50
*Param7 Description=damage synergy
Param8=1500
*Param8 Description=duration
InGame=1
HitShift=8
cost add=0
Looking back at Mon Hit Monster Effect, we see:

Code: Select all

aurastat2=passive_fire_mastery
aurastatcalc2=stat('skill_hex_effect'.accr)
aurastat3=passive_ltng_mastery
aurastatcalc3=stat('skill_hex_effect'.accr)
aurastat4=passive_cold_mastery
aurastatcalc4=stat('skill_hex_effect'.accr)
aurastat5=passive_pois_mastery
aurastatcalc5=stat('skill_hex_effect'.accr)
aurastat6=damagepercent
aurastatcalc6=stat('passive_hex_adddmg'.accr)
...which makes each monster hit temporarily apply Elemental Skill Damage % to the player, equal to the amount of skill_hex_effect that you applied with Hex. It will also apply Enhanced Damage % to the player, equal to the amount of passive_hex_adddmg that you applied with Hex.

The following formula is somewhat confusing:

Code: Select all

aurastat2=passive_hex_adddmg
aurastatcalc2=stat('passive_hex_adddmg'.accr)+(skill('Mana Sweep'.blvl)*par7)
This means "give the enemy passive_hex_adddmg equal to the amount of passive_hex_adddmg I have, plus synergies from Mana Sweep." Since you cannot gain passive_hex_adddmg through any means (unless another player casts Hex on you), it just means "give the enemy passive_hex_adddmg equal to synergies from Mana Sweep."

Hex also applies skill_holyinsanity_effect, which functions identically to Holy Insanity.
D2TXT / D2INI - Python scripts for editing TXT files, or converting between TXT ↔ INI files

User avatar
JDS
Junior Member
Paladin
Posts: 198
Joined: Wed Jun 05, 2013 8:31 pm

Re: Median 2008: Retaliate, Crucify, and other "when hit" skill mechanics

Post by JDS » Tue Jan 15, 2019 5:59 pm

Can't you decompile the bin files?
In any case, good job :) Very interesting

User avatar
mmpx222
Junior Member
Paladin
Posts: 154
Joined: Sat Apr 26, 2014 9:19 am
Korea South

Re: Median 2008: Retaliate, Crucify, and other "when hit" skill mechanics

Post by mmpx222 » Tue Jan 15, 2019 7:17 pm

JDS wrote:
Tue Jan 15, 2019 5:59 pm
Can't you decompile the bin files?
In any case, good job :) Very interesting
I don't know the format, and probably won't dissect BINs even if I knew how. Even if I did, I would probably be banned. Modders don't like the idea of others trying to access what they intentionally kept hidden. Also, the TOS explicitly says no (see section XXIV).
D2TXT / D2INI - Python scripts for editing TXT files, or converting between TXT ↔ INI files

Post Reply

Return to “Skill Clinic”