Skip to content
Carmina16 edited this page Apr 27, 2018 · 8 revisions

SPELLDATA record is defined in the save file formats.

The parameters Param0-5 each contain three entries, each of which is relative to one of the three possible effects a spell can have (specified in Effects).

Values for TargetType:

0x00 Self
0x01 Touch
0x02 Target

Values for Element:

0x00 Fire
0x01 Ice
0x02 Poison
0x03 Shock
0x04 Magic
0x05 None

Values for Effects/Subeffects:

0x00 Cause 
       0 Disease
       1 Poison
       2 Paralysis
       3 Curse
       4 Death
0x01 Continuous Damage
       0 Health
       1 Fatigue
       2 Spell points
0x02 Create 
       0 Shield
       1 Wall
       2 Floor
0x03 Cure 
       0 Disease
       1 Poison
       2 Paralysis
       3 Curse
0x04 Damage
       0 Health
       1 Fatigue
       2 Spell points
0x05 Designate as non-target
0x06 Destroy
       0 Wall
       1 Floor
       2 (not implemented)
0x07 Disintegrate
0x08 (not implemented)
0x09 Drain
       0 ???
       1 ???
0x0A Elemental resistance
0x0B Fortify attribute
0x0C Heal
       0 Stamina
       1 Health
       2 Spell points
       3 Attribute
0x0D Transfer Attribute
       0 Attribute
       1 Health/Stamina/SP
0x0E (unimplemented)
0x0F Invisibility
0x10 Levitate
0x11 Light
0x12 Lock	
0x13 Open
0x14 Regenerate
0x15 Silence
0x16 Spell Absorption
0x17 Spell Reflection
0x18 Spell Resistance

Magical effects

LVL is the 1-based caster level, as presented in the game UI. [] mean rounding down.

Cause disease

chance <- P0+[LVL/P4]*P1
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   duration <- LVL*P5
   unk1 <- P3
   magnitude <- -(P2)
   if target == player then
      disease <- randomFromList([10, 11, 12, 14, 15, 17, 19, 20, 21, 22, 24, 25, 26]
      target.addDisease(disease)
   else
      target.setStatusFlag(DISEASE)
      for i in (STR, AGI, SPD, END)
         target.stat[i] <- target.stat[i] + magnitude
   endif
else
   if caster == player then message("Failure")
endif

Cause poison

if target.hasEffect(POISON_RESIST) then return
if target.class == BARBARIAN then return
chance <- P0+[LVL/P4]*P1
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   duration <- LVL*P5
   unk1 <- P3
   magnitude <- -(P2)
   magnitude <- target.correctMagnitude(magnitude, POISON)
   target.addEffect(<poison>)
else
   if caster == player then message("Failure")
endif

Cause paralysis

if target.race == HIGH_ELF then return
if target.class == KNIGHT then return
chance <- P0+[LVL/P4]*P1
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   duration <- [LVL/P2]*P5 + P5
   target.addEffect(<paralyze>)
else
   if caster == player then message("Failure")
endif

Cause curse

chance <- P0+[LVL/P4]*P1
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   duration <- LVL*P5
   unk1 <- P3
   magnitude <- -(P2)
   target.setStatusFlag(CURSE)
   for i in (INT, WIL, PER, LUC)
      target.stat[i] <- target.stat[i] + magnitude
else
   if caster == player then message("Failure")
endif

Cause death

chance <- P0+[LVL/P4]*P1
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   target.kill()
else
   if caster == player then message("Failure")
endif

Continuous damage health

magnitude <- -(rnd(P1, P1 + 1) + rnd(P2, P3 + 1) * [LVL/P4])
duration <- P5
unk1 <- 1
magnitude <- target.damageShield(magnitude) # the magic shield
magnitude <- target.correctMagnitude(magnitude, element)
target.setStatusFlag(DRAINED)
target.addEffect(<dot>)

Continuous damage fatigue

magnitude <- -(rnd(P1, P1 + 1) + rnd(P2, P3 + 1) * [LVL/P4])
duration <- P5
unk1 <- 1
target.setStatusFlag(DRAINED)
target.addEffect(<dot to fatigue>)

Continuous damage spell points

magnitude <- -(rnd(P1, P1 + 1) + rnd(P2, P3 + 1) * [LVL/P4])
duration <- P5
unk1 <- 1
target.setStatusFlag(DRAINED)
target.addEffect(<dot to mana>)

Create shield

target.setShield(P0 + P1*[LVL/P4])
if caster == player then message("Success")

Create wall (floor)

if caster != player then return
if currentZoneType == CITY then
   message("Failure")
   return
endif
wallsToCreateDestroy <- P0 # (or floorsToCreateDestroy)

Cure disease (paralysis, curse)

chance <- P0 + P1 * [LVL/P4]
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   target.removeEffect(DISEASE) # PARALYSIS, CURSE
else
   if caster == player then message("Failure")
endif

Cure poison

chance <- P0 + P1 * [LVL/P4]
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   target.removeEffect(POISON)
   target.removeEffect(PARALYSIS) # sic
else
   if caster == player then message("Failure")
endif

Damage Health

magnitude <- -( rnd(P0, P1+1) + rnd(P2, P3+1) * [LVL/P4] )
magnitude <- target.damageShield(magnitude) # the magic shield
magnitude <- target.correctMagnitude(magnitude, element)
if target.hasEffect(REGENERATION) and target!=player then
   target.maxHP <- target.maxHP + magnitude
endif
target.curHP <- min(target.curHP + magnitude, target.maxHP)
if target==player then <check PC death>
<handle the target health change as after the physical attack>

Damage Stamina

magnitude <- -( rnd(P0, P1+1) + rnd(P2, P3+1) * [LVL/P4] )
target.curStamina <- target.curStamina + magnitude

Damage Spellpoints

magnitude <- -( rnd(P0, P1+1) + rnd(P2, P3+1) * [LVL/P4] )
target.curMana <- max(target.curMana + magnitude, 0)

Designate as non-target

chance <- P0 + P1 * [LVL/P4]
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   duration <- ([LVL/P2] + 1) * P5
   if flag & 0x100 then opt <- 0 else opt <- -1
   target.setTimer(TIMER_NONTARGET, duration, opt)
   target.addEffect(NONTARGET)
else
   if caster == player then message("Failure")

Destroy wall (floor)

if caster != player then return
if currentZoneType == CITY then
   message("Failure")
   return
endif
wallsToCreateDestroy <- -(P0) # (or floorsToCreateDestroy)

Desintegrate

chance <- P0 + P1 * [LVL/P4]
if chance > rnd() mod 100 then
   if caster == player then message("Success")
   target.curHP <- -1
   <handle the target health change as after the physical attack>
else
   if caster == player then message("Failure")

Drain Attribute (to do)

Elemental resistance

duration <- P0 + P1 * [LVL/P4]
chance <- P5 * [(player.level + 1)/P2]
target.setTimer(TIMER_FIRERESISTANCE+element, duration, chance)
target.addEffect(FIRERESISTANCE+element)

Different spell effects use different parameters:

Drain Attribute
    param0 pts of attribute drained for param5 rounds per level. Target recover
    attribute at param1 pts per param4 rounds

Fortify attribute
    +param0 pts of attribute for param5 rnds per level. attribute loss of param1
    pts per param4 rounds.

Heal attribute
    param0 to param1 pts to attribute +param2 to param3 per param4 levels

Transfer attribute
    Transfers param0 pts of attribute from target to caster

Invisibility
    param0 rounds + param1 rounds per param4 levels

Levitate
    param0 rounds + param1 rounds per param4 levels

Light
    param5 rounds per level

Lock
    param0 chance of locking. duration is param5 rounds per param2 levels
    lock strength + param1 % per param4 levels

Open
    param0 chance of unlocking, + param1% per param4 levels

Regenerate
    param0 health every param1 rounds for param4 rounds per level

Silence
    param0 chance of silencing for param5 rounds per param2 levels, + param1 % 
    per param4 levels

Spell Absorption
    param0 chance to absorb + param1 % per param4 levels. duration is param5 
    rounds per param2 levels

Spell reflection
    param0 chance to reflect + param1 % per param4 levels. duration is param5 
    rounds per param2 levels

Spell resistance
    param0 chance to resist + param1 % per param4 levels. duration is param5 
    rounds per param2 levels

Attributes

0 Strength
1 Intelligence
2 Willpower
3 Agility
4 Speed
5 Endurance
6 Personality
7 Luck

SPELLMKR.TXT

Record indices

(to do)

Variables

a  int     duration
b  string  "not" if (flag & 0x80)
c  string  attribute
e  string  "caster"
f  string  "is a projectile" if (flag & 0x80) else "follows the caster"
#  int     spell parameter
%  string  "%"
Clone this wiki locally