Using HHE with Heretic v1.3
For working with Heretic: Shadow of the Serpent Riders (aka Heretic v1.3) some changes to the default HHE.INI file are required. The values to use are as follows:
size = 728031 thingoff = 617600 soundoff = 639734 frameoff = 583860 spriteoff = 583348 ammooff = 635780 weaponoff = 636204 textoff = 563284 codepoff = 258020
HHE gives the wrong names for some of the things in the Things panel when used with v1.3. Heretic's internal thing table was altered between versions; the discrepancy begins at entry 88 and it seems that the "Phoenix Puff" object was removed. At this point, the next thing name after the thing in question is the one that the thing should actually have. Thing 159 is the wind ambient sound and thing 160 is the HHE clipboard as usual.
Things panel (F2)
The "burning frame" is actually a "crash frame" used when falling gargoyles splatter on the ground. Only players have a special burning death, and monsters cannot be given this property.
Table of Thing Flags
Several of the flag descriptions HHE gives for the thing bits are incomplete, unhelpful or outright incorrect. Here's a table of what internal names they correspond to and what they do, arranged in the same way that the HHE screen itself presents them.
|0 Gettable Thing
MF_SPECIAL: Will trigger thing pickup code depending on what the thing's sprite is currently set at. If the sprite is not on the list of valid gettables, the game will terminate.
MF_MISSILE: Handle this object as a missile.
MF_SOLID: Will block movement of other things.
|17 Disappearing Item
MF_DROPPED: Item will not respawn and can be crushed by moving sectors. Automatically set on items dropped by monsters.
|2 Shootable Thing
MF_SHOOTABLE: Handle this object as one which can be shot and damaged.
|18 Partial Invisibility
MF_SHADOW: Drawn translucent; when applied to shootable things, they are treated as ghosts (THRUGHOST projectiles pass through them without causing damage, staff cannot hit them, monsters have trouble targeting.) This is a single flag in standard Heretic, as opposed to ports which decouple translucency from ghostliness.
|3 Total Invisibility
MF_NOSECTOR: Used for certain invisible support objects like teleport destinations and pod/glitter spawners. Unsure of the separation between this and MF2_DONTDRAW, aside that NOSECTOR flagged items don't get linked to a subsector.
|19 Puffs (vs. bleeds)
MF_NOBLOOD: Don't spawn blood splatters when hit (used together with SHOOTABLE).
MF_NOBLOCKMAP: Don't link into the blockmap. Things with this flag set will be walk-through and shoot-through; overrides SHOOTABLE and SOLID if they are also set. By default, projectiles are flagged with this, among other things.
|20 Sliding Helpless
MF_CORPSE: Internally set on dead bodies to make them tumble down stairs.
MF_AMBUSH: Typically set by map designer rather than directly on enemies. Thing will not activate its chase sequence unless there is a line of sight to its intended target; hearing weapon fire gives it 360-degree vision but will not otherwise "awaken" it.
MF_INFLOAT: Used internally when an enemy is in the process of floating to a different height.
|6 In Pain
MF_JUSTHIT: Used internally for infighting retaliation. Setting it on a thing at spawn time makes projectile enemies respond aggressively when first activated but the flag will then be flipped back off.
|22 Counts for Kills
MF_COUNTKILL: Counts for kills on the end of level score. Is also treated as a monster for a few other purposes: -respawn and -nomonsters modes, and will also receive massive (gibbing) damage if a Massacre event is triggered (boss death event, cheat code)
MF_JUSTATTACKED: Used internally for projectile attack limiting when not on the top skill level. Setting it on a thing at spawn time makes projectile enemies less aggressive when first activated but the flag will then be flipped back off. If JUSTATTACKED and JUSTHIT are both set at spawn time, JUSTATTACKED is the one that holds sway.
|23 Counts for Items
MF_COUNTITEM: Counts for items on the end of level score.
|8 Hangs from Ceiling
MF_SPAWNCEILING: Start at ceiling height instead of on the ground. Will fall unless NOGRAVITY is also set.
MF_SKULLFLY: Used internally for swooping/charging monsters.
|9 No Gravity
MF_NOGRAVITY: Don't apply gravity; for example flying monsters and most missiles.
|25 Not in Deathmatch
MF_NOTDMATCH: Don't spawn in deathmatch games (used on keys, by default)
|10 Travels Up Cliffs
MF_DROPOFF: Ignore heights when crossing two-sided lines. Normally monsters and projectiles are blocked from crossing to a lower sector from a significantly higher one. This is typically set for projectiles and not set for monsters. Flying monsters do not need this. (It would be slightly more accurate to call this "Travels Down Cliffs", but has more to do with crossing boundaries than the direction traveled).
|26 Color 1 (yel./blue)
Color translation part 1. If just this part is set, dull green (palette entries 225 through 240) becomes yellow (114-129). If both translations flags are set, dull green becomes blue (190-205). By default it is set internally to differentiate players in multiplayer games, but can work on any sprite that uses the dull green palette range.
|11 Can pick up items
MF_PICKUP: Allows this thing to remove gettable items, normally set only on players. Does not appear to have an effect on non-player things.
|27 Color 2 (red/blue)
Color translation part 2. If just this part is set, dull green (palette entries 225 through 240) becomes red (145-160). If both translations flags are set, dull green becomes blue (190-205). By default it is set internally to differentiate players in multiplayer games, but can work on any sprite that uses the dull green palette range.
|12 No Clipping
MF_NOCLIP: Allows things to move through walls.
MF_SLIDE: Never used, does not trigger any code.
MF_FLOAT: Paired with NOGRAVITY, allow a monster to fly.
|15 Semi-No Clipping
MF_TELEPORT: Don't trigger line specials. Projectiles/charging monsters will "jump" to the nearest floor/ceiling on the other side when hitting a two-sided line (never used by default).
|0 Subject to Inertia
MF2_LOGRAV: Effect of gravity on this object is divided by 8.
|16 Causes Burning Death
MF2_FIREDAMAGE: Kills by things with this flag will initiate a burning death sequence for players and only players. Works when set on projectiles, and for monsters' melee attacks if set on the monster.
|1 Blown by Wind
MF2_WINDTHRUST: Wind sectors will push this object.
|17 Does Not Push Things
MF2_NODMGTHRUST: Doesn't cause damage momentum when hitting something (projectiles)
MF2_FLOORBOUNCE: For bouncing projectiles. The projectile is set to its death state upon hitting the floor, but can still deal damage after bouncing. Firemace code pointers can also be used at the start of the death sequence to reset the projectile to its spawn state (with other potential effects).
MF2_TELESTOMP: This thing is allowed to telefrag things if one sits at the destination point of an attempted teleport. If this flag is not set, the thing is forbidden to teleport to a blocked position.
|3 Goes Through Invis.
MF2_THRUGHOST: A projectile does not collide with things that have the SHADOW flag, instead passing through with no damage. No other effects (won't work on monsters, melee, or hitscans - immunity to staff jabs is handled separately in a hardcoded manner).
MF2_FLOATBOB: Object bobs up and down (used by default on some pickups). Highjacks the object's health variable to manage bobbing, randomizing it at level start and continually increasing it afterwards. Due to this, killable things given the flag will be almost invincible. Also manually sets object's vertical position, preventing free flight on mobile objects.
|4 Pushable Up Cliffs
MF2_FLY: Intended for players with Wings of Wrath and may be set/unset internally when used on a player object. On monsters or pushables, gives them certain altered flying player physics, which changes their friction and makes them attempt to drift up/down to a passable level when blocked by an object or two-sided wall, which can have potentially interesting (ab)uses.
MF2_DONTDRAW: Total invisibility, never consumes visible sprite quota. Used internally for picked-up items that are awaiting a respawn.
|5 Walks IN Liquids
MF2_FOOTCLIP: If an object has this flag, then the MF2_FEETARECLIPPED flag will be toggled if it moves into/out of a liquid floor.
|6 Starts on Floor
MF2_SPAWNFLOAT: Floating object is given a random vertical height at the start of the map. Exactly opposite of what HHE implies, flying monsters start on the floor if this flag is not set (excepting the effect of SPAWNCEILING).
|7 Does Not Teleport
MF2_NOTELEPORT: Forbidden from teleporting. Usually set on projectiles by default, which in Heretic can teleport if not flagged otherwise here.
|8 Dragon Claw Spikes (?)
MF2_RIP: Projectiles pass through shootable objects, doing repeated damage as they go.
MF2_PUSHABLE: If another thing bumps this thing, some momentum will be transferred unless the bumper is flagged CANNOTPUSH.
|10 Only Hits Monsters
MF2_SLIDE: "Slides" along walls, the path being deflected instead of blocked when hitting them; normally used for player and pushables. Projectiles also won't die when hitting walls/things and will generally act semi-similarly to MF2_RIP when hitting a monster. Use on regular projectiles is a bit strange, but combines well with FLOORBOUNCE on gravity-affected missiles to create the appearance of a projectile that bounces off both floors and walls.
MF2_ONMOBJ: Internal, set if standing on another object. Affects movement friction when set. (Also causes some strange effects as it is never unset by the game.)
MF2_PASSMOBJ: Allows this thing to move over/under other things (given to monsters). There is a hardcoded exception for Gargoyles and Disciples of D'Sparil that forbids them from going over/under each other, possibly related to the flying monsters sticking together bug.
|13: Particles (?)
MF2_CANNOTPUSH: This thing cannot push PUSHABLE things. If MISSILE is set, then this is irrelevant unless RIP is also set (rippers can push). For other projectiles see NODMGTHRUST instead.
MF2_FEETARECLIPPED: Used internally to handle standing in liquids, likely not useful for setting in hacks (the game adjusts it according to the floor the object is on). Instead, set FOOTCLIP on objects that you want the standing sunken in water effect to apply to.
|15: Varying Damage
MF2_BOSS: This thing is a boss monster. Affects infighting (no retaliation against bosses) and some weapon damage formulae such as rain and tomed mace instakills.
Frames panel (F3)
This section lets you adjust the frames list. This is the data that controls animation of things, as well as special actions in some cases.
"Bright Sprite" will flag a frame to be drawn at fullbright regardless of the light level of the sector the thing is in, for things like fire and glowing projectiles.
Changing the code pointer field here does nothing. If you want to change code pointers, you need to use the F8 Pointers screen. It is also worth noting that code pointers cannot be added to frames that have none, so some adjustment of the "next frame" properties may be necessary to get the desired effects. It may be desirable to reflect your pointer changes here as well, though, just in case.
Text panel (F7)
This section lets you change the game's text messages, like level names and episode end texts.
There are some specific requirements for the level names. Make sure they are in ALL CAPS and that they are prefaced in the format of "ExMx: " with two spaces after the colon (or, at least, that there are seven optional characters before the actual map title). These first seven characters appear on the automap screen but are removed from the string when displaying the level intermission screen.
Although HHE may insist on a minimum string length, this is usually incorrect, the maximum string length is the one that always matters. In most cases it's fine to pad the end of the string with spaces to fill out the length that HHE demands. In some cases, it may be necessary to manually edit the patch that HHE outputs, though, such as when WAD entry names must be referenced exactly.
If you go down enough pages in the text panel, you'll start encountering messed-up non-text "strings". It's another shortcoming of the program, and these should not be touched. You may need to keep an eye out for your patches getting corrupted due to these, too.
Pointers panel (F8)
This is where you can reassign the functions that certain frames will perform. This is unfortunately an unintuitive section of the program, with no clear indication what frames the pointers are attached to or what the offsets mean. Without a reference table, most things have to be discovered by some educated guesswork and a lot of trial and error.
Essentially, each offset represents a location in the EXE where an action function begins; HHE presents the offsets in decimal rather than hex, and they correspond to runtime offsets rather than file ones. By changing them, you can set the corresponding frame to perform a different action than it would by default. When altering code pointers on the code pointer screen, you can direct the execution pretty much anywhere in the program. This could have useful effects but is also potentially risky to experiment indiscriminately with (you could crash the game or your computer if you send the execution to instructions that are invalid). It is highly advised to stick to the known valid offsets.
Weapon codepointers should not be used on monsters, and monster codepointers should not be used on weapons. The best way to put a monster attack on a weapon or vice versa is by altering thing and frame properties to emulate the attack.
Table of pointer references for v1.3
This table is intended to help you match the code pointers to their frames. It is currently incomplete.
|25||236||Frame only accessed by IDKFA cheat|
|37||262||Chicken beak lower, used if chicken player dies|
|43||263||Chicken beak raise, likely unused|
|44||274||Powered gauntlet raise|
|45||273||Powered gauntlet lower|
|46||272||Powered gauntlet ready|
|47||271||Powered gauntlet ready|
|48||270||Powered gauntlet ready|
|49||269||Unpowered gauntlet ready|
|50||280||Unpowered gauntlet refire|
|51||279||Gauntlet unp fire|
|52||278||Gauntlet unp fire|
|53||277||Gauntlet unp fire|
|54||286||Gauntlet p fire|
|55||285||Gauntlet p fire|
|57||281||Gauntlet unp unflash|
|58||288||Gauntlet p unflash|
|59||287||Gauntlet p refire|
|67||312||Claw p refire|
|71||354||A_ReFire - 114256||S_MACEATK1_6|
|72||A_FireMacePL1 - 116208|
|73||A_FireMacePL1 - 116208|
|74||A_FireMacePL1 - 116208|
|75||A_FireMacePL1 - 116208|
|76||360||A_FireMacePL2 - 117056||S_MACEATK2_2|
|77||365||A_MaceBallImpact - 116464||S_MACEFXI1_1|
|78||A_MacePL1Check - 116352|
|79||A_MacePL1Check - 116352|
|80||362||A_ReFire - 114256||S_MACEATK2_4|
|81||372||A_MaceBallImpact2 - 116624|
|96||A_RainImpact - 118688|
|97||A_RainImpact - 118688|
|98||A_RainImpact - 118688|
|99||A_RainImpact - 118688|
|100||A_Raise - 114480|
|101||A_Lower - 114320|
|102||A_WeaponReady - 113728|
|107||A_Raise - 114480|
|108||A_Lower - 114320|
|109||A_WeaponReady - 113728|
|110||A_FirePhoenixPL2 - 119136|
|111||A_InitPhoenixPL2 - 119120|
|112||481||A_ReFire - 114256||Phoenix PL1 refire|
|113||478||A_FirePhoenixPL1 - 118784|
|114||487||A_Explode - 79312||Phoenix blast explode|
|117||484||Phoenix roaster refire|
|120||A_WeaponReady - 113728|
|121||A_WeaponReady - 113728|
|122||A_WeaponReady - 113728|
|123||A_WeaponReady - 113728|
|124||A_WeaponReady - 113728|
|125||A_WeaponReady - 113728|
|126||A_WeaponReady - 113728|
|127||A_WeaponReady - 113728|
|128||A_WeaponReady - 113728|
|129||A_WeaponReady - 113728|
|130||A_WeaponReady - 113728|
|131||A_WeaponReady - 113728|
|132||A_WeaponReady - 113728|
|133||A_WeaponReady - 113728|
|134||A_WeaponReady - 113728|
|135||A_WeaponReady - 113728|
|136||A_WeaponReady - 113728|
|138||A_Raise - 114480|
|139||A_Lower - 114320|
|140||A_WeaponReady - 113728|
|144||551||A_ReFire - 114256||S_CRBOWATK2_8|
|145||A_Scream - 78640|
|146||A_Pain - 72560|
|147||A_Look - 71792|
|148||A_Look - 71792|
|149||A_Look - 71792|
|150||A_Look - 71792|
|151||A_Scream - 78640|
|152||A_Pain - 72560|
|153||706||A_BeastAttack - 77184|
|154||A_FaceTarget - 72464|
|155||A_NoBlocking - 78896|
|156||A_Scream - 78640|
|157||A_BeastPuff - 73056|
|158||A_BeastPuff - 73056|
|159||A_NoBlocking - 78896|
|160||A_AddPlayerCorpse - 81168|
|161||A_NoBlocking - 78896|
|162||A_NoBlocking - 78896|
|163||589||A_SkullPop - 80816|
|164||A_Scream - 78640|
|165||A_FlameSnd - 81264|
|167||A_FlameSnd - 81264|
|168||A_Scream - 78640|
|169||A_NoBlocking - 78896|
|170||A_CheckSkullFloor - 80976|
|171||A_CheckSkullFloor - 80976|
|172||615||A_CheckBurnGone - 81040|
|173||622||A_CheckSkullDone - 81008|
|174||A_CheckSkullFloor - 80976|
|175||A_CheckSkullFloor - 80976|
|176||A_CheckSkullFloor - 80976|
|177||A_Feathers - 74144|
|178||A_Feathers - 74144|
|179||A_ChicChase - 74064|
|180||A_ChicChase - 74064|
|181||A_ChicLook - 74032|
|182||A_ChicLook - 74032|
|183||A_Pain - 72560|
|184||A_Feathers - 74144|
|185||A_Scream - 78640|
|186||639||A_ChicAttack - 73952|
|187||A_FaceTarget - 72464|
|188||637||A_ChicPain - 74096|
|189||A_NoBlocking - 78896|
|190||661||A_Chase - 71920||S_MUMMY_WALK3|
|191||660||A_Chase - 71920||S_MUMMY_WALK2|
|192||659||A_Chase - 71920||S_MUMMY_WALK1|
|193||658||A_Look - 71792||S_MUMMY_LOOK2|
|194||657||A_Look - 71792||S_MUMMY_LOOK1|
|195||667||A_FaceTarget - 72464||S_MUMMYL_ATK2|
|196||666||A_FaceTarget - 72464||S_MUMMYL_ATK1|
|197||665||A_FaceTarget - 72464||S_MUMMY_ATK3|
|198||664||A_MummyAttack - 74352||S_MUMMY_ATK2|
|199||663||A_FaceTarget - 72464||S_MUMMY_ATK1|
|200||662||A_Chase - 71920||S_MUMMY_WALK4|
|201||673||A_Pain - 72560||S_MUMMY_PAIN2|
|202||671||A_MummyAttack2 - 74464||S_MUMMYL_ATK6|
|203||670||A_FaceTarget - 72464||S_MUMMYL_ATK5|
|204||669||A_FaceTarget - 72464||S_MUMMYL_ATK4|
|205||668||A_FaceTarget - 72464||S_MUMMYL_ATK3|
|206||678||A_NoBlocking - 78896||S_MUMMY_DIE5|
|207||676||A_MummySoul - 74592||S_MUMMY_DIE3|
|208||675||A_Scream - 78640||S_MUMMY_DIE2|
|209||692||A_MummyFX1Seek - 74560||S_MUMMYFX1_4|
|210||690||A_MummyFX1Seek - 74560||S_MUMMYFX1_2|
|211||689||A_ContMobjSound - 111056||S_MUMMYFX1_1|
|212||698||A_Look - 71792||S_BEAST_LOOK2|
|213||697||A_Look - 71792||S_BEAST_LOOK1|
|214||A_Chase - 71920|
|215||A_Chase - 71920|
|216||A_Chase - 71920|
|217||A_BeastPuff - 73056|
|218||A_BeastPuff - 73056|
|219||A_BeastPuff - 73056|
|220||A_BeastPuff - 73056|
|221||759||A_Look - 71792||S_SNAKE_LOOK2|
|222||758||A_Look - 71792||S_SNAKE_LOOK1|
|223||A_FaceTarget - 72464|
|224||A_FaceTarget - 72464|
|225||A_Chase - 71920|
|226||A_Chase - 71920|
|227||A_Chase - 71920|
|228||A_Chase - 71920|
|229||A_FaceTarget - 72464|
|230||A_FaceTarget - 72464|
|231||A_FaceTarget - 72464|
|232||A_SnakeAttack - 78112|
|233||A_SnakeAttack - 78112|
|234||A_SnakeAttack - 78112|
|235||776||A_Scream - 78640||S_SNAKE_DIE2|
|236||774||A_Pain - 72560||S_SNAKE_PAIN2|
|237||772||A_SnakeAttack2 - 78192||S_SNAKE_ATK9|
|238||781||A_NoBlocking - 78896||S_SNAKE_DIE7|
|239||802||A_FaceTarget - 72464||S_HEAD_ATK1|
|240||801||A_Chase - 71920||S_HEAD_FLOAT|
|241||800||A_Look - 71792||S_HEAD_LOOK|
|242||807||A_Scream - 78640||S_HEAD_DIE2|
|243||805||A_Pain - 72560||S_HEAD_PAIN2|
|244||803||A_HeadAttack - 77296||S_HEAD_ATK2|
|245||812||A_BossDeath - 79872||S_HEAD_DIE7|
|246||810||A_NoBlocking - 78896||S_HEAD_DIE5|
|247||816||A_HeadIceImpact - 77888||S_HEADFXI1_1|
|248||A_HeadFireGrow - 78048|
|249||A_HeadFireGrow - 78048|
|250||A_HeadFireGrow - 78048|
|251||A_WhirlwindSeek - 77728|
|252||A_WhirlwindSeek - 77728|
|253||A_WhirlwindSeek - 77728|
|254||851||A_Chase - 71920||S_CLINK_WALK2|
|255||850||A_Chase - 71920||S_CLINK_WALK1|
|256||849||A_Look - 71792||S_CLINK_LOOK2|
|257||848||A_Look - 71792||S_CLINK_LOOK1|
|258||856||A_ClinkAttack - 78272||S_CLINK_ATK3|
|259||855||A_FaceTarget - 72464||S_CLINK_ATK2|
|260||854||A_FaceTarget - 72464||S_CLINK_ATK1|
|261||853||A_Chase - 71920||S_CLINK_WALK4|
|262||852||A_Chase - 71920||S_CLINK_WALK3|
|263||862||A_NoBlocking - 78896||S_CLINK_DIE4|
|264||861||A_Scream - 78640||S_CLINK_DIE3|
|265||858||A_Pain - 72560||S_CLINK_PAIN2|
|266||870||A_Chase - 71920||S_WIZARD_WALK3|
|267||869||A_Chase - 71920||S_WIZARD_WALK2|
|268||868||A_Chase - 71920||S_WIZARD_WALK1|
|269||867||A_Look - 71792||S_WIZARD_LOOK2|
|270||866||A_Look - 71792||S_WIZARD_LOOK1|
|271||873||A_Chase - 71920||S_WIZARD_WALK6|
|272||872||A_Chase - 71920||S_WIZARD_WALK5|
|273||970||A_Scream - 78640||S_KNIGHT_DIE2|
|274||976||A_ContMobjSound - 111056||S_SPINAXE1|
|275||983||A_DripBlood - 72592||S_REDAXE2|
|276||982||A_DripBlood - 72592||S_REDAXE1|
|277||993||A_Sor1Pain - 74640|
|278||992||A_Sor1Chase - 74688||S_SRCR1_WALK4|
|279||991||A_Sor1Chase - 74688||S_SRCR1_WALK3|
|280||990||A_Sor1Chase - 74688||S_SRCR1_WALK2|
|281||989||A_Sor1Chase - 74688||S_SRCR1_WALK1|
|282||988||A_Look - 71792||S_SRCR1_LOOK2|
|283||987||A_Look - 71792||S_SRCR1_LOOK1|
|284||999||A_FaceTarget - 72464||S_SRCR1_ATK6|
|285||998||A_FaceTarget - 72464||S_SRCR1_ATK5|
|286||997||A_FaceTarget - 72464||S_SRCR1_ATK4|
|287||996||A_Srcr1Attack - 74736||S_SRCR1_ATK3|
|288||995||A_FaceTarget - 72464||S_SRCR1_ATK2|
|289||994||A_FaceTarget - 72464||S_SRCR1_ATK1|
|290||1002||A_Scream - 78640||S_SRCR1_DIE2|
|291||1000||A_Srcr1Attack - 74736||S_SRCR1_ATK7|
|292||1008||A_SorZap - 76000||S_SRCR1_DIE8|
|293||1017||A_SorcererRise - 75024||S_SRCR1_DIE17|
|294||1012||A_SorZap - 76000||S_SRCR1_DIE12|
|295||876||A_WizAtk1 - 78384||S_WIZARD_ATK1|
|296||875||A_Chase - 71920||S_WIZARD_WALK8|
|297||874||A_Chase - 71920||S_WIZARD_WALK7|
|298||882||A_WizAtk1 - 78384||S_WIZARD_ATK7|
|299||881||A_WizAtk2 - 78416||S_WIZARD_ATK6|
|300||880||A_WizAtk1 - 78384||S_WIZARD_ATK5|
|301||879||A_WizAtk2 - 78416||S_WIZARD_ATK4|
|302||878||A_WizAtk1 - 78384||S_WIZARD_ATK3|
|303||877||A_WizAtk2 - 78416||S_WIZARD_ATK2|
|304||888||A_Scream - 78640||S_WIZARD_DIE2|
|305||887||A_GhostOff - 78368||S_WIZARD_DIE1|
|306||886||A_Pain - 72560||S_WIZARD_PAIN2|
|307||885||A_GhostOff - 78368||S_WIZARD_PAIN1|
|308||884||A_WizAtk3 - 78448||S_WIZARD_ATK9|
|309||883||A_WizAtk2 - 78416||S_WIZARD_ATK8|
|310||891||A_NoBlocking - 78896||S_WIZARD_DIE5|
|311||A_Look - 71792|
|312||A_Look - 71792|
|313||A_Look - 71792|
|314||A_Look - 71792|
|315||A_Look - 71792|
|316||A_Look - 71792|
|317||A_Chase - 71920|
|318||A_Chase - 71920|
|319||A_Chase - 71920|
|320||A_Chase - 71920|
|321||A_Chase - 71920|
|322||A_Chase - 71920|
|323||918||A_ImpMsAttack - 73248||S_IMP_MSATK1_2|
|324||A_FaceTarget - 72464|
|325||916||A_ImpMeAttack - 73168||S_IMP_MEATK3|
|326||A_FaceTarget - 72464|
|327||A_FaceTarget - 72464|
|328||925||A_ImpMsAttack2 - 73456||S_IMP_MSATK2_3|
|329||A_FaceTarget - 72464|
|330||A_FaceTarget - 72464|
|331||930||A_ImpXDeath1 - 73600||S_IMP_XDIE1|
|332||928||A_ImpDeath - 73552||S_IMP_DIE1|
|333||927||A_Pain - 72560||S_IMP_PAIN2|
|334||936||A_Scream - 78640||S_IMP_CRASH2|
|335||935||A_ImpExplode - 72880||S_IMP_CRASH1|
|336||933||A_ImpXDeath2 - 73648||S_IMP_XDIE4|
|337||A_Look - 71792|
|338||A_Look - 71792|
|339||A_FaceTarget - 72464|
|340||A_FaceTarget - 72464|
|341||A_Chase - 71920|
|342||A_Chase - 71920|
|343||A_Chase - 71920|
|344||A_Chase - 71920|
|345||968||A_Pain - 72560||S_KNIGHT_PAIN2|
|346||966||A_KnightAttack - 72736||S_KNIGHT_ATK6|
|347||965||A_FaceTarget - 72464||S_KNIGHT_ATK5|
|348||964||A_FaceTarget - 72464||S_KNIGHT_ATK4|
|349||963||A_KnightAttack - 72736||S_KNIGHT_ATK3|
|350||972||A_NoBlocking - 78896||S_KNIGHT_DIE4|
|351||1028||A_SorRise - 76032||S_SOR2_RISE3|
|352||A_Chase - 71920|
|353||A_Chase - 71920|
|354||A_Look - 71792|
|355||A_Look - 71792|
|356||1032||A_SorSightSnd - 76160||S_SOR2_RISE7|
|357||1042||A_FaceTarget - 72464||S_SOR2_ATK2|
|358||1041||A_Srcr2Decide - 75360||S_SOR2_ATK1|
|359||1040||A_Pain - 72560||S_SOR2_PAIN2|
|360||1038||A_Chase - 71920||S_SOR2_WALK4|
|361||1037||A_Chase - 71920||S_SOR2_WALK3|
|362||1043||A_Srcr2Attack - 75440|
|363||1052||A_SorDSph - 76064||S_SOR2_DIE3|
|364||1050||A_Sor2DthInit - 75936||S_SOR2_DIE1|
|365||1060||A_SorDBon - 76128||S_SOR2_DIE11|
|366||1059||A_NoBlocking - 78896||S_SOR2_DIE10|
|367||1056||A_SorDExp - 76096||S_SOR2_DIE7|
|368||1055||A_Sor2DthLoop - 75968||S_SOR2_DIE6|
|369||1066||A_BlueSpark - 75664||S_SOR2FX1_2|
|370||1065||A_BlueSpark - 75664||S_SOR2FX1_1|
|371||1064||A_BossDeath - 79872||S_SOR2_DIE15|
|372||1068||A_Explode - 79312||S_SOR2FXI1_1|
|373||1067||A_BlueSpark - 75664||S_SOR2FX1_3|
|374||1078||A_GenWizard - 75776||S_SOR2FX2_2|
|375||1091||A_Look - 71792||S_MNTR_LOOK1|
|376||1097||A_FaceTarget - 72464||S_MNTR_ATK1_1|
|377||1096||A_Chase - 71920||S_MNTR_WALK4|
|378||1095||A_Chase - 71920||S_MNTR_WALK3|
|379||1094||A_Chase - 71920||S_MNTR_WALK2|
|380||1093||A_Chase - 71920||S_MNTR_WALK1|
|381||1092||A_Look - 71792||S_MNTR_LOOK2|
|382||1103||A_FaceTarget - 72464||S_MNTR_ATK3_1|
|383||1102||A_MinotaurAtk2 - 76656||S_MNTR_ATK2_3|
|384||1101||A_FaceTarget - 72464||S_MNTR_ATK2_2|
|385||1100||A_MinotaurDecide - 76304||S_MNTR_ATK2_1|
|386||1099||A_MinotaurAtk1 - 76192||S_MNTR_ATK1_3|
|387||1098||A_FaceTarget - 72464||S_MNTR_ATK1_2|
|388||1109||A_Pain - 72560||S_MNTR_PAIN2|
|389||1107||A_MinotaurCharge - 76576||S_MNTR_ATK4_1|
|390||1105||A_MinotaurAtk3 - 76896||S_MNTR_ATK3_3|
|391||1104||A_FaceTarget - 72464||S_MNTR_ATK3_2|
|392||1112||A_Scream - 78640||S_MNTR_DIE3|
|393||1117||A_NoBlocking - 78896||S_MNTR_DIE8|
|394||1124||A_BossDeath - 79872||S_MNTR_DIE15|
|395||1134||A_Explode - 79312||S_MNTRFXI2_1|
|396||1133||A_MntrFloorFire - 77072||S_MNTRFX2_1|
|399||Invalid||Invalid||Do not alter|
|400||Invalid||Invalid||Do not alter|
Table of action pointer offsets
Here are the action pointers as named in the Heretic source code, their corresponding HHE offsets, and what function they perform. Frame reference numbers are based on v1.3 of the Heretic EXE and may differ in earlier versions.
Some actions have a hardcoded sound effect initiated by them as well, which is not always noted on these descriptions.
|A_Look||71792||Monster - Watch for a player to target|
|A_Chase||71920||Monster - Move around, try to approach current target|
|A_FaceTarget||72464||Monster - Adjust angle to face towards target|
|A_Pain||72560||Play the calling thing's pain sound, if there is one (customizable with thing properties).|
|A_DripBlood||72592||Spawn a blood drip thing.|
|A_KnightAttack||72736||Monster - Deal 1d8×3 damage at melee range, otherwise if caller is a ghost knight or by random chance throw a red axe, otherwise throw a green axe.|
|A_ImpExplode||72880||Throw one of each of the two gargoyle gib things in a random direction. Potentially forces the calling actor into frame 939.|
|A_BeastPuff||73056||Approximately 1/4 chance to spawn weredragon fireball's smoke puffs with somewhat randomized spawn position.|
|A_ImpMeAttack||73168||Monster - Melee attack for 5 to 12 damage.|
|A_ImpMsAttack||73248||Monster - Thing charges at target (gargoyle swoop). Random chance to not attack and go back to sight state instead.|
|A_ImpMsAttack2||73456||Monster - Deal 5 to 12 damage at melee range, or else throw a gargoyle fireball.|
|A_ImpDeath||73552||Handles gargoyle death fall, forces thing to frame 935 when it hits the floor.|
|A_ImpXDeath1||73600||Setup flags (unsets solid, sets nogravity and footclip) and special for gargoyle crash splatter.|
|A_ImpXDeath2||73648||Unsets nogravity flag, checks if thing has hit floor and if so forces its state to frame 935.|
|A_ChicAttack||73952||Calls some internal checking for chickens , if passed, do a melee attack for 1 to 2 damage. What does it do?|
|A_ChicLook||74032||Calls some internal checking for chickens, if passed, do A_Look|
|A_ChicChase||74064||Calls some internal checking for chickens, if passed, do A_Chase|
|A_ChicPain||74096||Calls some internal checking for chickens, then plays the calling thing's pain sound.|
|A_Feathers||74144||Randomly spawn one or two feathers if the calling thing is alive, or 5 to 8 of them if the caller is dead.|
|A_MummyAttack||74352||Monster - Melee attack for 1d8×2 damage (Golem punch).|
|A_MummyAttack2||74464||Deal 1d8×2 damage to target at melee range or else launch a flaming skull projectile (Nitrogolem attack)|
|A_MummyFX1Seek||74560||Seeking function for nitrogolem projectiles.|
|A_MummySoul||74592||Spawns a golem soul with upwards momentum.|
|A_Sor1Pain||74640||Sets the calling thing's special variable to 20 (for Chaos Serpent rage speedup), then calls A_Pain|
|A_Sor1Chase||74688||If the calling thing's special variable is set, decrement it and speed up the thing's animation. Then calls A_Chase.|
|A_Srcr1Attack||74736||Deal 1d8×8 damage at melee range, or shoot chaos serpent fireballs. If health is less than 2/3 max then fires spreadshots. If health is less than 1/3 max then additionally gets a random chance for double attacks (can force thing's frame to 997).|
|A_SorcererRise||75024||Spawn thing D'Sparil on foot and makes the calling actor non-blocking. Sets the spawned D'Sparil into frame 1026.|
|A_Srcr2Decide||75360||By random chance weighted by thing's level of HP remaining, potentially pick one of D'Sparil's teleport destinations and warp there.|
|A_Srcr2Attack||75440||Monster - Deal 1d8×20 damage at melee range, otherwise by random chance weighted by thing's remaining HP, either shoot two summoning rings to the sides or one thunderbolt at the target.|
|A_BlueSpark||75664||Spawn a thunderbolt sparkle with randomized momentum|
|A_GenWizard||75776||Spawn a Disciple of D'Sparil if there is space; calling actor then enters its death state and spawns a teleport flash.|
|A_Sor2DthInit||75936||Set actor's special variable to 7 and kill all monsters|
|A_Sor2DthLoop||75968||Decrements the actor's special variable and if it's still not zero, set actor's frame to 1052.|
|A_SorZap||76000||Play sound "sorzap".|
|A_SorRise||76032||Play sound "sorrise".|
|A_SorDSph||76064||Play sound "sordsph".|
|A_SorDExp||76096||Play sound "sordexp".|
|A_SorDBon||76128||Play sound "sordbon".|
|A_SorSightSnd||76160||Play sound "sorsit".|
|A_MinotaurAtk1||76192||Maulotaur hammer smash for 1d8×4 melee damage, knocks player view down, hardcoded hit sound "stfpow"|
|A_MinotaurDecide||76304||Maulotaur multi-attack handler and charging initiator. Can force calling thing into frame 1103 or 1107.|
|A_MinotaurCharge||76576||Maulotaur charging handler, spawns phoenix smoke puffs and decrements special counter, ends charge if counter has run down. Actual charge is initiated by A_MinotaurDecide.|
|A_MinotaurAtk2||76656||Fire a spreadshot of 5 maulotaur fire shots or do 1d8×5 melee damage, depending on target range|
|A_MinotaurAtk3||76896||1d8×5 melee strike if in range, or spawn Maulotaur fire trail head, random chance of looping to frame 1106|
|A_MntrFloorFire||77072||Do Maulotaur floor fire trail, spawns fire tail|
|A_BeastAttack||77184||Do 1d8×3 damage at melee range or else shoot a weredragon fireball.|
|A_HeadAttack||77296||Deals 1d8×6 damage at melee range or else fire an iron lich projectile: possibilities are ice ball, fire (potentially forced to frame 830), or tornado.|
|A_WhirlwindSeek||77728||Handler for tornado seeking its target.|
|A_HeadIceImpact||77888||Fire a ring of 8 Iron Lich ice shards (designed to be called from a projectile, monsters may hurt themselves if they call it directly).|
|A_HeadFireGrow||78048||Counts down using the things health variable, adjusting its vertical position. When health is 0, force frame to 830.|
|A_SnakeAttack||78112||Fires Ophidian shot type 1, or forces actor to frame 760 if no target|
|A_SnakeAttack2||78192||Fires Ophidian shot type 2, or forces actor to frame 760 if no target|
|A_ClinkAttack||78272||Melee attack for 8 to 10 damage (Sabreclaw slash)|
|A_GhostOff||78368||Removes the ghost flag from the calling thing.|
|A_WizAtk1||78384||Calls A_FaceTarget and removes the ghost flag from the calling thing.|
|A_WizAtk2||78416||Calls A_FaceTarget and sets the ghost flag on the calling thing.|
|A_WizAtk3||78448||Removes the ghost flag from the calling thing, deal 1d8×4 damage at melee range or else fire a spread of three wizard shots.|
|A_Scream||78640||Plays a thing's death sound. Maulotaurs, mounted D'Sparils, and chicken players make full-volume screams. Players make one of four different sounds depending on the intensity of death . Otherwise just makes the death sound normally. Note the sound names|
|A_NoBlocking||78896||Unsets the SOLID flag, and also does random item drops for certain thing types.|
|A_Explode||79312||Deal blast damage. Time Bombs, Maulotaur fire and D'Sparil lightning have some individual hardcoded effects here, everything else just explodes like a Doom rocket/barrel.|
|A_PodPain||79424||Randomly spawn pod particles. Randomly according to what?|
|A_RemovePod||79584||Decrement parent's special variable (pod spawn limiting counter).|
|A_MakePod||79632||As long as the calling actor's special variable is not 16, attempt to create a pod if there is space. The new pod's frame is forced to 103.|
|A_BossDeath||79872||Handle boss monster death specials (tag 666 when map number is 8), with hardcoded boss types per episode (Iron Lich, Maulotaur, D'Sparil, Iron Lich, Maulotaur respectively). Potentially kill all other monsters if episode is not E1.|
|A_ESound||80000||Play waterfall or wind sounds. Thing type is hardcoded and does not work for any other thing number, and HHE does not conveniently extend to these things. Sounds won't play on other things.|
|A_SpawnTeleGlitter||80048||Spawner for teleport glitter.|
|A_SpawnTeleGlitter2||80128||Spawner for exit glitter.|
|A_AccTeleGlitter||80208||Increment calling actor's health variable and if it exceeds 35, increase vertical momentum by 50% of its current value.|
|A_InitKeyGizmo||80256||Create an orb. The frame of this orb is decided by the calling thing's type. Note the possible results properly.|
|A_VolcanoSet||80352||Randomizes the tic duration of the calling thing's current frame, from 105 to 232.|
|A_VolcanoBlast||80384||Volcano eruption launching 1 to 3 large lava balls|
|A_VolcBallImpact||80608||Handle explosion of a lava ball, spawning for little lava bits.|
|A_SkullPop||80816||Spawns a player's decapitated head, attaches player's view to it (not advisable to use on non-players) I'm sure bad things may happen if used on a non-player, but what are they?|
|A_CheckSkullFloor||80976||If calling thing has hit floor, force it to frame 622.|
|A_CheckSkullDone||81008||If calling things's special2 variable has reached 666, force thing's frame to 623.|
|A_CheckBurnGone||81040||If calling things's special2 variable has reached 666, force thing's frame to 616.|
|A_FreeTargMobj||81072||Unsets SHOOTABLE, SOLID, FLOAT, SKULLFLY, PASSMOBJ, and LOGRAV flags, sets CORPSE, DROPOFF, NOGRAVITY flags, detaches thing from a player.|
|A_AddPlayerCorpse||81168||Manage a list for existing player corpses and delete an old one if there are too many. The cap appears to be 32.|
|A_FlameSnd||81264||Play sound "headat1".|
|A_HideThing||81296||Set calling thing's DONTDRAW flag.|
|A_UnHideThing||81312||Unset calling thing's DONTDRAW flag.|
|A_RestoreArtifact||84528||Respawns an item, with a respawning sound effect.|
|A_RestoreSpecialThing1||84608||If the calling thing is a firemace, then call the mace pickup randomizer. Regardless, make the calling thing visible and play a respawn sound.|
|A_RestoreSpecialThing2||84656||Respawn an item, without sound.|
|A_ContMobjSound||111056||Hardcoded sound handler for projectiles, if the calling thing type is a knight axe plays sound "kgtatk", for nitrogolem shots plays "mumhed". Does nothing otherwise.|
|A_WeaponReady||113728||Weapon - placed on frames where the weapon is prepared to respond to the player's fire button. Contains some special handling, for instance, if called from frame 240 then there is a random chance of playing sound "stfcrk". Description implies there's other special handling, what?|
|A_BeakReady||114128||Weapon - Special handling for chicken beak's ready states|
|A_ReFire||114256||Weapon - Check if the player is holding down the fire button, and continue firing the weapon if appropriate.|
|A_Lower||114320||Weapon - Handler for putting a weapon away (lowers sprite towards bottom of screen and switches weapons when it's lowered enough.) Also handles weapon disappearing from screen if player is killed.|
|A_BeakRaise||114416||Weapon - Special handler for the chicken beak becoming the current weapon. Weapon raising is done instantly and does not take into account Tome of Power status.|
|A_Raise||114480||Weapon - Handler for selecting a new weapon, shows sprite rising onto the screen and selects weapon ready state depending on if the Tome of Power is active.|
|A_BeakAttackPL1||114720||Weapon - Beak peck, melee attack for 1 to 4 damage and sets player's "chickenPeck" variable to 12.|
|A_BeakAttackPL2||114896||Weapon - Super beak peck, melee attack for 1d8×4 damage and sets player's "chickenPeck" variable to 12.|
|A_StaffAttackPL1||115088||Weapon - Staff normal jab, deal 5 to 20 melee damage (no ammo)|
|A_StaffAttackPL2||115232||Weapon - Staff tomed jab, deal 18 to 81 melee damage (no ammo)|
|A_FireBlasterPL1||115376||Weapon - Dragon Claw fire, hitscan for 1d8×4 damage, accuracy decreases if refiring (1 energy orb)|
|A_FireBlasterPL2||115520||Weapon - Dragon Claw tomed fire, launches a tomed claw projectile (thing #65) which is given special fast-projectile movement logic (5 energy orbs)|
|A_FireGoldWandPL1||115600||Weapon - Elven Wand fire, hitscan for 7 to 14 damage, accuracy decreases if refiring (1 wand crystal)|
|A_FireGoldWandPL2||115744||Weapon - Elven Wand tomed fire, launch two wand projectiles at angles, plus a spread of five hitscans that do 1 to 8 damage each (1 wand crystal)|
|A_FireMacePL1||116208||Weapon - Firemace fire, usually fires a small mace ball, but has random chance to lob a larger ball with momentum affected by the firing player's momentum (1 mace sphere)|
|A_MacePL1Check||116352||Decrements the calling thing's special variable and if it's brought to or below 0, turn on the LOGRAV flag and adjust its angle/momentum.|
|A_MaceBallImpact||116464||Handle mace balls bouncing or landing in liquid, also being destroyed when done bouncing.|
|A_MaceBallImpact2||116624||Similar to the above but also spawns a pair of tiny mace balls.|
|A_FireMacePL2||117056||Weapon - Firemace tomed fire, lobs a giant ball with momentum affected by the firing player's movement (5 mace spheres)|
|A_DeathBallImpact||117184||Handles bouncing and target-seeking properties of the giant mace ball.|
|A_SpawnRippers||117520||Tomed Dragon Claw blast ring, spawns a ring of eight claw rippers.|
|A_FireCrossbowPL1||117664||Weapon - Crossbow fire, shoot one centered large bolt and two small ones at angles (1 arrow)|
|A_FireCrossbowPL2||117744||Weapon - Crossbow tomed fire, shoot three super bolts and two small ones (1 arrow)|
|A_BoltSpark||117888||Spawns crossbow bolt glitter.|
|A_FireSkullRodPL1||118000||Weapon - Hellstaff fire, shoot a projectile with a random chance to force the projectile's frame to 394 (1 rune)|
|A_FireSkullRodPL2||118080||Weapon - Hellstaff tomed fire, shoot a tomed projectile, uses special variable for seeking/sounds and special 2 variable to remember owning player (5 runes)|
|A_SkullRodPL2Seek||118208||Calls seeking missile function with parameters set for Hellstaff's tomed shots|
|A_AddPlayerRain||118240||Handler for initializing acid rain storms from Hellstaff|
|A_SkullRodStorm||118416||Spawn raindrops, thing type varies depending on the calling actor's special 2 variable (different color rain for the four players).|
|A_RainImpact||118688||Potentially set thing's frame to 437 through 440 depending on it's special 2 variable.|
|A_HideInCeiling||118752||Move the calling thing up into the ceiling.|
|A_FirePhoenixPL1||118784||Weapon - Phoenix Rod fire, launch a phoenix projectile and apply recoil momentum to the firing player|
|A_PhoenixPuff||118896||Spawns two Phoenix shot smoke trails.|
|A_InitPhoenixPL2||119120||Weapon - sets firing player's "flamecount" variable to 350.|
|A_FirePhoenixPL2||119136||Weapon - Decreases player's flamecount variable and forces weapon frame to 485 if the fire has run out, otherwise shoots phoenix flames with influence from player's momentum.|
|A_ShutdownPhoenixPL2||119504||Weapon - Decrements player's Phoenix Rod ammo (1 flame orb)|
|A_FlameEnd||119520||Adjusts calling thing's vertical momentum.|
|A_FloatPuff||119552||Adjusts calling thing's vertical momentum.|
|A_GauntletAttack||119584||Weapon - Gauntlet, if player is Tomed, do extended-range melee for 1d8×2 damage with red puff and life steal for half of damage dealt, otherwise do 1d8×2 melee damage with green puff, both modes also set weapon light flash.|
|A_Light0||120064||Weapon - Turns off weapon's light flash|
These are just some of the other special behaviors that are hardcoded to particular thing or frame numbers, etc. which are not noted or alterable in HHE. There may be others.
Thing #122 (Disciple of D'Sparil) and thing #124 (Gargoyle) are forbidden from moving over/under other things of these two types even if they have PASSMOBJ set.
Thing #122 (Disciple of D'Sparil) has a 50% chance of using its sight sound instead of its active sound when playing active sounds.
Thing #135 (dismounted D'Sparil) will not retaliate against thing #122 (Disciple) in infighting.
Thing #135 (dismounted D'Sparil) makes active sounds at full volume regardless of distance.
Thing #133 (mounted D'Sparil), thing #135 (dismounted D'Sparil) and thing #140 (maulotaur) are immune to splash damage from any source.
Useful for making a small addition without having to disrupt the rest of the game's behavior, Heretic v1.3 does have some unused data that should be able to be recycled without incident:
Thing #82 (described as "Wand Shot PL1") is an unused thing.
Frames 460 and 461 are frames whose only association is with the unused Thing #82.
Frame 263 appears to be unused despite being referenced. It would be the chicken beak raise state, but in-game testing suggests that the beak is already set in the ready state whenever players are morphed into chickens and when chicken players are reloaded from saved games. It has an associated codepointer in slot 43.
Check duplicate weredragon ball objects and confirm that they're unused as well.
Possible uses of these include adding a new scenery object or adding a ghost variant of a monster (such as the elusive ghost weredragon, perhaps).