- importing Witchaven code from GDX

This is a straight port of the GDX Java code to C++ with as few changes made as possible.
Part 1: AI code.
This commit is contained in:
Christoph Oelckers 2020-10-02 22:22:46 +02:00
parent c93b8f3e54
commit 96637a25d1
34 changed files with 10861 additions and 0 deletions

View file

@ -1339,3 +1339,4 @@ add_subdirectory( games/duke )
add_subdirectory( blood )
add_subdirectory( sw )
add_subdirectory( exhumed )
add_subdirectory( games/whaven )

View file

@ -20,6 +20,9 @@
#define BEGIN_PS_NS namespace Exhumed {
#define END_PS_NS }
#define BEGIN_WH_NS namespace Witchaven {
#define END_WH_NS }
#else
#define BEGIN_EDUKE_NS

View file

@ -0,0 +1,31 @@
set( PCH_SOURCES
src/ai.cpp
src/aidemon.cpp
src/aidevil.cpp
src/aidragon.cpp
src/aifatwitch.cpp
src/aifish.cpp
src/aifred.cpp
src/aigoblin.cpp
src/aigonzo.cpp
src/aigron.cpp
src/aiguardian.cpp
src/aiimp.cpp
src/aijudy.cpp
src/aikatie.cpp
src/aikobold.cpp
src/aikurt.cpp
src/aiminotaur.cpp
src/ainewguy.cpp
src/airat.cpp
src/aiskeleton.cpp
src/aiskully.cpp
src/aispider.cpp
src/aiwillow.cpp
src/names.cpp
)
add_game_library2( whaven )
include_directories( src )

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,142 @@
#pragma once
#include "wh.h"
BEGIN_WH_NS
struct EnemyInfo
{
short sizx, sizy;
int attackdist;
int attackdamage;
int attackheight;
short health;
bool fly;
int clipdist;
int score;
void Init(int sizx, int sizy, int dist, int height, int damage, int clipdist, bool fly, int health, int score)
{
this->sizx = (short) sizx;
this->sizy = (short) sizy;
this->attackdist = dist;
this->attackheight = height;
this->attackdamage = damage;
this->clipdist = clipdist;
this->fly = fly;
this->health = (short) health;
this->score = score;
}
short (*getHealth)(EnemyInfo& e, SPRITE& spr) = [](EnemyInfo& e, SPRITE& spr)
{
return adjusthp(e.health);
};
int (*getAttackDist)(EnemyInfo& e, SPRITE& spr) = [](EnemyInfo &e, SPRITE& spr)
{
return e.attackdist;
};
void set(SPRITE &spr)
{
spr.clipdist = clipdist;
spr.hitag = getHealth(*this, spr);
if(sizx != -1)
spr.xrepeat = sizx;
if(sizy != -1)
spr.yrepeat = sizy;
spr.lotag = 100;
int tflag = 0;
if((spr.cstat & 514) != 0)
tflag = spr.cstat & 514;
spr.cstat = (short) (0x101 | tflag);
}
};
using AIState = void (*)(PLAYER &plr, short i);
struct Enemy
{
EnemyInfo info;
AIState patrol;
AIState chase;
AIState resurect;
AIState nuked;
AIState frozen;
AIState pain;
AIState face;
AIState attack;
AIState flee;
AIState cast;
AIState die;
AIState skirmish;
AIState stand;
AIState search;
};
enum EEnemy
{
DEMONTYPE = 1, // ok
DEVILTYPE = 2, // nuked ok, frozen no
DRAGONTYPE = 3, // wh1
FATWITCHTYPE = 4, // wh1
FISHTYPE = 5,
FREDTYPE = 6,
GOBLINTYPE = 7, // wh1
GONZOTYPE = 8, // freeze nuke ok
GRONTYPE = 9, // ok
GUARDIANTYPE = 10, // nuke ok
IMPTYPE = 11, // freeze nuke ok
JUDYTYPE = 12, // wh1
KATIETYPE = 13, // ok
KOBOLDTYPE = 14, // freeze nuke ok
KURTTYPE = 15,
MINOTAURTYPE = 16, // freeze nuke ok
NEWGUYTYPE = 17, // freeze nuke ok
RATTYPE = 18,
SKELETONTYPE = 19, // freezee nuke ok
SKULLYTYPE = 20, // wh1
SPIDERTYPE = 21, // wh1
WILLOWTYPE = 22, //nuke ok
MAXTYPES = 23,
};
enum EAIConst
{
TYPENONE = 0,
TYPEWATER = 1,
TYPELAVA = 2,
};
extern Enemy enemy[MAXTYPES];
void aiProcess();
int aimove(short i);
int aifly(short i);
void aisearch(PLAYER& plr, short i, boolean fly);
boolean checksector6(short i);
int checkfluid(int i, int zr_florhit);
void processfluid(int i, int zr_florhit, boolean fly);
void castspell(PLAYER& plr, int i);
void skullycastspell(PLAYER& plr, int i);
void attack(PLAYER& plr, int i);
int checkmove(short i, int dax, int day);
boolean checkdist(PLAYER& plr, int i);
boolean checkdist(int i, int x, int y, int z);
extern int checksight_ang;
boolean checksight(PLAYER& plr, int i);
void monsterweapon(int i);
PLAYER& aiGetPlayerTarget(short i);
boolean actoruse(short i);
inline int findplayer() {
return 0; // no multiplayer support, apparently...
}
END_WH_NS

View file

@ -0,0 +1,231 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
if (plr.z < spr.z) {
spr.z -= TICSPERFRAME << 8;
}
if (plr.z > spr.z) {
spr.z += TICSPERFRAME << 8;
}
short osectnum = spr.sectnum;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum) && plr.invisibletime < 0)
newstatus(i, ATTACK);
return;
}
else {
if (totalclock % 100 > 70)
trailingsmoke(i, true);
int dax = ((sintable[(sprite[i].ang + 512) & 2047] * TICSPERFRAME) << 2);
int day = ((sintable[sprite[i].ang & 2047] * TICSPERFRAME) << 2);
checksight(plr, i);
if (!checkdist(plr, i)) {
checkmove(i, dax, day);
}
else {
if (plr.invisibletime < 0) {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, CHASE); // NEW
}
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
checksector6(i);
processfluid(i, zr_florhit, true);
if (sector[osectnum].lotag == KILLSECTOR && spr.z + (8 << 8) >= sector[osectnum].floorz) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
if (spr.z + (8 << 8) >= sector[osectnum].floorz) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, true);
checksector6(i);
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = DEMON;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aifly(i);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (plr.z < spr.z) {
spr.z -= TICSPERFRAME << 8;
}
if (plr.z > spr.z) {
spr.z += TICSPERFRAME << 8;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aifly(i);
if (movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, true);
setsprite(i, spr.x, spr.y, spr.z);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (plr.z < spr.z) {
spr.z -= TICSPERFRAME << 8;
}
if (plr.z > spr.z) {
spr.z += TICSPERFRAME << 8;
}
if (spr.lotag < 0) {
castspell(plr, i);
newstatus(i, CHASE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
}
void createDemonAI() {
auto& e = enemy[DEMONTYPE];
enemy[DEMONTYPE].info.Init(38, 41, 4096 + 2048, 120, 0, 64, true, 300, 0);
e.chase = chase;
e.resurect;
e.nuked = nuked;
e.frozen;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die;
e.skirmish;
e.stand;
e.search = search;
}
void premapDemon(short i) {
SPRITE& spr = sprite[i];
spr.detail = DEMONTYPE;
changespritestat(i, FACE);
enemy[DEMONTYPE].info.set(spr);
}

View file

@ -0,0 +1,280 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum) && plr.invisibletime < 0)
newstatus(i, ATTACK);
}
else {
checksight(plr, i);
if (!checkdist(plr, i)) {
if ((aimove(i) & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
}
else {
if (plr.invisibletime < 0) {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, FLEE); // NEW
}
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == DEVILDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = DEVIL;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
sprite[i].extra -= TICSPERFRAME;
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = DEVIL;
spr.hitag = (short)adjusthp(60);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = DEVIL;
newstatus(i, FACE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
return;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == DEVILCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == DEVILATTACK + 2) {
spr.picnum = DEVIL;
playsound_loc(S_FIREBALL, sprite[i].x, sprite[i].y);
castspell(plr, i);
newstatus(i, CHASE);
}
checksector6(i);
}
void createDevilAI() {
auto &e = enemy[DEVILTYPE];
e.info.Init(game.WH2 ? 50 : 36, game.WH2 ? 50 : 36, 2048, 120, 0, 64, false, 50, 0);
e.chase = chase;
e.die = die;
e.pain = pain;
e.face = face;
e.flee = flee;
e.attack = attack;
e.resurect = resurect;
e.search = search;
e.frozen = frozen;
e.nuked = nuked;
e.cast = cast;
}
void premapDevil(short i) {
SPRITE& spr = sprite[i];
spr.detail = DEVILTYPE;
changespritestat(i, FACE);
enemy[DEVILTYPE].info.set(spr);
if (spr.pal == 2)
spr.hitag = adjusthp(60);
}
END_WH_NS

View file

@ -0,0 +1,420 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static int checksight_x, checksight_y = 0;
static void checkspeed(int i, int speed);
static void dragonAttack2(PLAYER& plr, short i);
static void firebreath(PLAYER& plr, int i, int a, int b, int c);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
// int speed = 10;
if ((krand() % 16) == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0)
if (plr.z < spr.z)
newstatus(i, ATTACK2);
else
newstatus(i, ATTACK);
return;
}
else {
int dax = (sintable[(sprite[i].ang + 512) & 2047] * TICSPERFRAME) << 3;
int day = (sintable[sprite[i].ang & 2047] * TICSPERFRAME) << 3;
// checkspeed(i, speed);
checksight(plr, i);
if (!checkdist(plr, i)) {
// checkmove(i, checksight_x, checksight_y);
checkmove(i, dax, day);
}
else {
if (plr.invisibletime < 0) {
if (krand() % 8 == 0) { // NEW
if (plr.z < spr.z)
newstatus(i, ATTACK2);
else
newstatus(i, ATTACK);
}
else { // NEW
newstatus(i, FACE); // NEW
}
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == DRAGONDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
switch (spr.picnum) {
case DRAGONATTACK + 17:
case DRAGONATTACK + 4:
if ((krand() % 2) != 0)
playsound_loc(S_FLAME1, spr.x, spr.y);
else
playsound_loc(S_FIREBALL, spr.x, spr.y);
firebreath(plr, i, 1, 2, LOW);
break;
case DRAGONATTACK + 18:
case DRAGONATTACK + 5:
if ((krand() % 2) != 0)
playsound_loc(S_FLAME1, spr.x, spr.y);
else
playsound_loc(S_FIREBALL, spr.x, spr.y);
firebreath(plr, i, 2, 1, LOW);
break;
case DRAGONATTACK + 19:
case DRAGONATTACK + 6:
if ((krand() % 2) != 0)
playsound_loc(S_FLAME1, spr.x, spr.y);
else
playsound_loc(S_FIREBALL, spr.x, spr.y);
firebreath(plr, i, 4, 0, LOW);
break;
case DRAGONATTACK + 20:
case DRAGONATTACK + 7:
firebreath(plr, i, 2, -1, LOW);
break;
case DRAGONATTACK + 21:
case DRAGONATTACK + 8:
firebreath(plr, i, 1, -2, LOW);
break;
case DRAGONATTACK2 + 2:
if ((krand() % 2) != 0)
playsound_loc(S_FLAME1, spr.x, spr.y);
else
playsound_loc(S_FIREBALL, spr.x, spr.y);
firebreath(plr, i, 1, -1, HIGH);
break;
case DRAGONATTACK2 + 3:
firebreath(plr, i, 2, 0, HIGH);
break;
case DRAGONATTACK2 + 5:
spr.picnum = DRAGON;
newstatus(i, CHASE);
break;
case DRAGONATTACK + 22:
spr.picnum = DRAGONATTACK;
newstatus(i, CHASE);
break;
}
checksector6(i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = DRAGON;
spr.hitag = (short)adjusthp(900);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, true);
checksector6(i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = DRAGON;
newstatus(i, FACE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == DRAGONCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
void dragonProcess(PLAYER& plr)
{
for (short i = headspritestat[ATTACK2], nextsprite; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
SPRITE& spr = sprite[i];
switch (spr.detail) {
case DRAGON:
dragonAttack2(plr, i);
break;
}
}
}
static void dragonAttack2(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0)
newstatus(i, CAST);
else
newstatus(i, CHASE);
return;
}
else
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
checksector6(i);
}
void dragonProcess(PLAYER& plr)
{
for (short i = headspritestat[ATTACK2], nextsprite; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
SPRITE& spr = sprite[i];
switch (spr.detail) {
case DRAGON:
dragonAttack2(plr, i);
break;
}
}
}
static void dragonAttack2(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0)
newstatus(i, CAST);
else
newstatus(i, CHASE);
return;
}
else
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
checksector6(i);
}
static void firebreath(PLAYER& plr, int i, int a, int b, int c) {
for (int k = 0; k <= a; k++) {
int j = insertsprite(sprite[i].sectnum, MISSILE);
if (j == -1)
return;
sprite[j].x = sprite[i].x;
sprite[j].y = sprite[i].y;
if (c == LOW)
sprite[j].z = sector[sprite[i].sectnum].floorz - (32 << 8);
else
sprite[j].z = sector[sprite[i].sectnum].floorz - (tilesizy[sprite[i].picnum] << 7);
sprite[j].cstat = 0;
sprite[j].picnum = MONSTERBALL;
sprite[j].shade = -15;
sprite[j].xrepeat = 128;
sprite[j].yrepeat = 128;
sprite[j].ang = (short)((((getangle(plr.x - sprite[j].x, plr.y - sprite[j].y)
+ (krand() & 15) - 8) + 2048) + ((b * 22) + (k * 10))) & 2047);
sprite[j].xvel = (short)(sintable[(sprite[j].ang + 2560) & 2047] >> 6);
sprite[j].yvel = (short)(sintable[(sprite[j].ang + 2048) & 2047] >> 6);
int discrim = ksqrt(
(plr.x - sprite[j].x) * (plr.x - sprite[j].x) + (plr.y - sprite[j].y) * (plr.y - sprite[j].y));
if (discrim == 0)
discrim = 1;
if (c == HIGH)
sprite[j].zvel = (short)(((plr.z + (32 << 8) - sprite[j].z) << 7) / discrim);
else
sprite[j].zvel = (short)((((plr.z + (8 << 8)) - sprite[j].z) << 7) / discrim);// NEW
sprite[j].owner = (short)i;
sprite[j].clipdist = 16;
sprite[j].lotag = 512;
sprite[j].hitag = 0;
}
}
static void checkspeed(int i, int speed) {
checksight_x = (sintable[(sprite[i].ang + 512) & 2047] >> speed);
checksight_y = (sintable[sprite[i].ang & 2047] >> speed);
}
void createDragonAI() {
auto& e = enemy[DRAGONTYPE];
e.info.Init(54, 54, 512, 120, 0, 128, false, 900, 0);
e.chase = chase;
e.flee = flee;
e.die = die;
e.cast = cast;
e.attack = attack;
e.resurect = resurect;
e.search = search;
e.frozen = frozen;
e.nuked = nuked;
e.pain = pain;
e.face = face;
}
void premapDragon(short i) {
SPRITE& spr = sprite[i];
spr.detail = DRAGONTYPE;
changespritestat(i, FACE);
enemy[DRAGONTYPE].info.set(spr);
}

View file

@ -0,0 +1,288 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))// && invisibletime < 0)
newstatus(i, ATTACK);
}
else {
checksight(plr, i);
if (!checkdist(i, plr.x, plr.y, plr.z)) {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, FLEE); // NEW
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = FATWITCH;
spr.hitag = (short)adjusthp(90);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == FATWITCHCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = FATWITCH;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7), spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(i, plr.x, plr.y, plr.z))
newstatus(i, ATTACK);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == FATWITCHATTACK + 3) {
sprite[i].picnum = FATWITCH;
throwspank(plr, i);
newstatus(i, CHASE);
}
checksector6(i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == FATWITCHDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
void throwspank(PLAYER& plr, int i) {
int j = insertsprite(sprite[i].sectnum, MISSILE);
if (j == -1)
return;
playsound_loc(S_WITCHTHROW, sprite[i].x, sprite[i].y);
sprite[j].x = sprite[i].x;
sprite[j].y = sprite[i].y;
sprite[j].z = sector[sprite[i].sectnum].floorz - ((tilesizy[sprite[i].picnum] >> 1) << 8);
sprite[j].cstat = 0; // Hitscan does not hit other bullets
sprite[j].picnum = FATSPANK;
sprite[j].shade = -15;
sprite[j].xrepeat = 64;
sprite[j].yrepeat = 64;
sprite[j].ang = (short)(((getangle(plr.x - sprite[j].x, plr.y - sprite[j].y) + (krand() & 15)
- 8) + 2048) & 2047);
sprite[j].xvel = (short)(sintable[(sprite[j].ang + 2560) & 2047] >> 6);
sprite[j].yvel = (short)(sintable[(sprite[j].ang + 2048) & 2047] >> 6);
long discrim = ksqrt((plr.x - sprite[j].x) * (plr.x - sprite[j].x) + (plr.y - sprite[j].y) * (plr.y - sprite[j].y));
if (discrim == 0)
discrim = 1;
sprite[j].zvel = (short)(((plr.z + (48 << 8) - sprite[j].z) << 7) / discrim);
sprite[j].owner = (short)i;
sprite[j].clipdist = 16;
sprite[j].lotag = 512;
sprite[j].hitag = 0;
sprite[j].pal = 0;
}
void createFatwitchAI() {
auto& e = enemy[FATWITCHTYPE];
e.info.Init(32, 32, 2048, 120, 0, 64, false, 280, 0);
e.chase = chase;
e.resurect = resurect;
e.search = search;
e.nuked = nuked;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die = die;
}
void premapFatwitch(short i) {
SPRITE& spr = sprite[i];
spr.detail = FATWITCHTYPE;
changespritestat(i, FACE);
enemy[FATWITCHTYPE].info.set(spr);
if (spr.pal == 7)
spr.hitag = (short)adjusthp(290);
if (krand() % 100 > 50)
spr.extra = 1;
}
END_WH_NS

View file

@ -0,0 +1,196 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
}
static void die(PLAYER& plr, short i) {
deletesprite(i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.z = sector[sprite[i].sectnum].floorz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag >= 64) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
if (aimove(i) != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
void createFishAI() {
auto &e = enemy[FISHTYPE];
e.info.Init(1, 1, 512, 120, 0, 32, false, 10, 0);
e.chase = chase;
e.die = die;
e.attack = attack;
e.skirmish = skirmish;
e.search = search;
e.face = face;
}
void premapFish(short i) {
SPRITE& spr = sprite[i];
spr.detail = FISHTYPE;
changespritestat(i, FACE);
enemy[FISHTYPE].info.set(spr);
}
END_WH_NS

View file

@ -0,0 +1,332 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
if (aimove(i) != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == FREDDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = FRED;
newstatus(i, FACE);
}
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag >= 64) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if (movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = FRED;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = FRED;
spr.hitag = (short)adjusthp(40);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createFredAI() {
auto &e = enemy[FREDTYPE];
e.info.Init(48, 48, 1024 + 256, 120, 0, 64, false, 40, 0);
e.chase = chase;
e.skirmish = skirmish;
e.die = die;
e.search = search;
e.frozen = frozen;
e.face = face;
e.attack = attack;
e.flee = flee;
e.pain = pain;
e.resurect = resurect;
}
void premapFred(short i) {
SPRITE& spr = sprite[i];
if (spr.picnum == FRED && spr.pal == 1) {
deletesprite(i);
return;
}
spr.detail = FREDTYPE;
changespritestat(i, FACE);
enemy[FREDTYPE].info.set(spr);
if (krand() % 100 > 50)
spr.extra = 1;
}
END_WH_NS

View file

@ -0,0 +1,581 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == GOBLINDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = GOBLIN;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
spr.picnum = GOBLIN;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void stand(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (sintable[(spr.ang + 2560) & 2047] * (plr.x - spr.x)
+ sintable[(spr.ang + 2048) & 2047] * (plr.y - spr.y) >= 0)
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
switch (spr.picnum) {
case GOBLINCHILL:
spr.picnum = GOBLINSURPRISE;
playsound_loc(S_GOBPAIN1 + (krand() % 2), spr.x, spr.y);
newstatus(i, CHILL);
break;
default:
spr.picnum = GOBLIN;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
break;
}
}
checksector6(i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag == 31) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
spr.picnum = GOBLIN;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = GOBLIN;
spr.hitag = (short)adjusthp(35);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = GOBLIN;
newstatus(i, FACE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == GOBLINCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
void goblinChill(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 18;
if (spr.picnum == GOBLINSURPRISE + 5) {
spr.picnum = GOBLIN;
newstatus(i, FACE);
}
}
}
static void goblinWar(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short k;
if (spr.lotag > 256) {
spr.lotag = 100;
spr.extra = 0;
}
switch (spr.extra) {
case 0: // find new target
long olddist = 1024 << 4;
boolean found = false;
for (k = 0; k < MAXSPRITES; k++) {
if (sprite[k].picnum == GOBLIN && spr.pal != sprite[k].pal && spr.hitag == sprite[k].hitag) {
long dist = klabs(spr.x - sprite[k].x) + klabs(spr.y - sprite[k].y);
if (dist < olddist) {
found = true;
olddist = dist;
spr.owner = k;
spr.ang = getangle(sprite[k].x - spr.x, sprite[k].y - spr.y);
spr.extra = 1;
}
}
}
if (!found) {
if (spr.pal == 5)
spr.hitag = (short)adjusthp(35);
else if (spr.pal == 4)
spr.hitag = (short)adjusthp(25);
else
spr.hitag = (short)adjusthp(15);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, FACE);
}
break;
case 1: // chase
k = spr.owner;
int movehit = aimove(i);
if (movehit == 0)
spr.ang = getangle(sprite[k].x - spr.x, sprite[k].y - spr.y);
else if ((movehit & kHitTypeMask) == kHitWall) {
spr.extra = 3;
spr.ang = (short)((spr.ang + (krand() & 256 - 128)) & 2047);
spr.lotag = 60;
}
else if ((movehit & kHitTypeMask) == kHitSprite) {
int sprnum = movehit & kHitIndexMask;
if (sprnum != k) {
spr.extra = 3;
spr.ang = (short)((spr.ang + (krand() & 256 - 128)) & 2047);
spr.lotag = 60;
}
else spr.ang = getangle(sprite[k].x - spr.x, sprite[k].y - spr.y);
}
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checkdist(i, sprite[k].x, sprite[k].y, sprite[k].z)) {
spr.extra = 2;
}
else
spr.picnum = GOBLIN;
if (checksector6(i))
return;
break;
case 2: // attack
k = spr.owner;
if (checkdist(i, sprite[k].x, sprite[k].y, sprite[k].z)) {
if ((krand() & 1) != 0) {
// goblins are fighting
// JSA_DEMO
if (krand() % 10 > 6)
playsound_loc(S_GENSWING, spr.x, spr.y);
if (krand() % 10 > 6)
playsound_loc(S_SWORD1 + (krand() % 6), spr.x, spr.y);
if (checkdist(plr, i))
addhealth(plr, -(krand() & 5));
if (krand() % 100 > 90) { // if k is dead
spr.extra = 0; // needs to
spr.picnum = GOBLIN;
sprite[k].extra = 4;
sprite[k].picnum = GOBLINDIE;
sprite[k].lotag = 20;
sprite[k].hitag = 0;
newstatus(k, DIE);
}
else { // i attack k flee
spr.extra = 0;
sprite[k].extra = 3;
sprite[k].ang = (short)((spr.ang + (krand() & 256 - 128)) & 2047);
sprite[k].lotag = 60;
}
}
}
else {
spr.extra = 1;
}
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
break;
case 3: // flee
spr.lotag -= TICSPERFRAME;
if (aimove(i) != 0)
spr.ang = (short)(krand() & 2047);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag < 0) {
spr.lotag = 0;
spr.extra = 0;
}
if (checksector6(i))
return;
break;
case 4: // pain
spr.picnum = GOBLINDIE;
break;
case 5: // cast
break;
}
checkexpl(plr, i);
}
void goblinWarProcess(PLAYER& plr)
{
for (short i = headspritestat[WAR], nextsprite; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
SPRITE& spr = sprite[i];
switch (spr.detail) {
case GOBLINTYPE:
goblinWar(plr, i);
break;
}
}
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createGoblinAI() {
auto& e = enemy[GOBLINTYPE];
e.info.Init(36, 36, 1024, 120, 0, 64, false, 15, 0);
e.chase = chase;
e.die = die;
e.pain = pain;
e.face = face;
e.flee = flee;
e.stand = stand;
e.attack = attack;
e.resurect = resurect;
e.search = search;
e.frozen = frozen;
e.nuked = nuked;
e.skirmish = skirmish;
e.info.getHealth = [](EnemyInfo& e, SPRITE& spr)
{
if (spr.pal == 5)
return adjusthp(35);
else if (spr.pal == 4)
return adjusthp(25);
return adjusthp(e.health);
};
}
void premapGoblin(short i) {
SPRITE& spr = sprite[i];
spr.detail = GOBLINTYPE;
if (spr.hitag < 90 || spr.hitag > 99)
enemy[GOBLINTYPE].info.set(spr);
else {
short ohitag = spr.hitag;
enemy[GOBLINTYPE].info.set(spr);
if (spr.pal != 0)
spr.xrepeat = 30;
spr.extra = 0;
spr.owner = 0;
spr.hitag = ohitag;
return;
}
if (spr.picnum == GOBLINCHILL) {
changespritestat(i, STAND);
spr.lotag = 30;
if (krand() % 100 > 50)
spr.extra = 1;
return;
}
changespritestat(i, FACE);
if (krand() % 100 > 50)
spr.extra = 1;
}
END_WH_NS

View file

@ -0,0 +1,783 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void gonzopike(short s, PLAYER& plr);
static void checkexpl(PLAYER& plr, short i);
static boolean patrolprocess(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
switch (spr.picnum) {
case GONZOGHM:
case GONZOGSH:
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
newstatus(i, ATTACK);
}
break;
}
else if ((krand() & 0) == 1) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
break;
}
int dax = spr.x; // Back up old x&y if stepping off cliff
int day = spr.y;
int daz = spr.z;
osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if (zr_florz > spr.z + (48 << 8)) {
spr.x = dax;
spr.y = day;
spr.z = daz;
setsprite(i, spr.x, spr.y, spr.z);
movestat = 1;
if (rand() % 100 > 80 && sector[plr.sector].lotag == 25) {
newstatus(i, AMBUSH);
sprite[i].z -= (getPlayerHeight() << 6);
sprite[i].lotag = 60;
sprite[i].extra = 1;
sprite[i].picnum = GONZOHMJUMP;
return;
}
}
if ((movestat & 0xc000) == 32768 && sector[plr.sector].lotag == 25) {
newstatus(i, AMBUSH);
sprite[i].z -= (getPlayerHeight() << 6);
sprite[i].lotag = 90;
sprite[i].extra = 3;
sprite[i].picnum = GONZOHMJUMP;
return;
}
if (movestat != 0) {
if ((movestat & 4095) != plr.spritenum) {
int daang;
if ((krand() & 0) == 1)
daang = (spr.ang + 256) & 2047;
else
daang = (spr.ang - 256) & 2047;
spr.ang = (short)daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
newstatus(i, SKIRMISH);
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
break;
}
else {
if (!patrolprocess(plr, i))
newstatus(i, FLEE);
}
break;
case GONZOCSW:
case GONZOGSW:
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
if (!patrolprocess(plr, i))
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
}
checkexpl(plr, i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
switch (spr.picnum) {
case GONZOCSWDEAD:
spr.picnum = GONZOCSW;
spr.hitag = (short)adjusthp(50);
break;
case GONZOGSWDEAD:
spr.picnum = GONZOGSW;
spr.hitag = (short)adjusthp(100);
break;
case GONZOGHMDEAD:
spr.picnum = GONZOGHM;
spr.hitag = (short)adjusthp(40);
break;
case GONZOGSHDEAD:
spr.picnum = GONZOGSH;
spr.hitag = (short)adjusthp(50);
break;
}
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus(i, DIE);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
switch (sprite[i].picnum) {
case GONZOCSWPAIN:
spr.picnum = GONZOCSW;
break;
case GONZOGSWPAIN:
spr.picnum = GONZOGSW;
break;
case GONZOGHMPAIN:
spr.picnum = GONZOGHM;
break;
case GONZOGSHPAIN:
spr.picnum = GONZOGSH;
break;
}
newstatus(i, FACE);
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
switch (sprite[i].picnum) {
case GONZOCSWPAIN:
spr.picnum = GONZOCSW;
break;
case GONZOGSWPAIN:
spr.picnum = GONZOGSW;
break;
case GONZOGHMPAIN:
spr.picnum = GONZOGHM;
break;
case GONZOGSHPAIN:
spr.picnum = GONZOGSH;
break;
}
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (plr.invisibletime < 0 && checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
switch (spr.picnum) {
// WANGO
case KURTREADY:
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
}
break;
case KURTREADY + 1:
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = KURTAT;
spr.lotag = 64;
}
break;
case KURTAT:
case KURTPUNCH:
if (spr.lotag == 46) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
break;
case GONZOCSWAT:
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
break;
case GONZOGSWAT:
case GONZOGHMAT:
case GONZOGSHAT:
if (spr.lotag == 31) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
break;
}
checksector6(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
if (plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == GONZOCSWAT) {
spr.extra--;
playsound_loc(S_GENTHROW, spr.x, spr.y);
gonzopike(i, plr);
newstatus(i, CHASE);
}
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
switch (sprite[i].picnum) {
case GONZOBSHDEAD:
case GONZOCSWDEAD:
case GONZOGSWDEAD:
case GONZOGHMDEAD:
case GONZOGSHDEAD:
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
break;
}
}
}
void gonzoProcess(PLAYER& plr)
{
short nextsprite;
for (short i = headspritestat[LAND]; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.lotag = 12;
spr.picnum++;
}
switch (spr.picnum) {
case GONZOHMJUMPEND:
spr.picnum = GONZOGSH;
spr.detail = GONZOTYPE;
enemy[GONZOTYPE].info.set(spr);
sprite[i].hitag = adjusthp(100);
newstatus(i, FACE);
break;
case GONZOSHJUMPEND:
spr.picnum = GONZOGSH;
spr.detail = GONZOTYPE;
enemy[GONZOTYPE].info.set(spr);
sprite[i].hitag = adjusthp(100);
newstatus(i, FACE);
break;
}
}
short movestat;
for (short i = headspritestat[AMBUSH]; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
SPRITE& spr = sprite[i];
switch (spr.extra) {
case 1: // forward
spr.zvel += TICSPERFRAME << 3;
movestat = (short)movesprite(i, ((sintable[(spr.ang + 512) & 2047]) * TICSPERFRAME) << 3,
((sintable[spr.ang]) * TICSPERFRAME) << 3, spr.zvel, 4 << 8, 4 << 8, 0);
spr.lotag -= TICSPERFRAME;
if (zr_florz <= spr.z && spr.lotag < 0) {
spr.z = zr_florz;
changespritestat(i, LAND);
}
if ((movestat & 0xc000) == 49152) { // Bullet hit a sprite
int k = (movestat & 4095);
for (int j = 0; j < 15; j++) {
shards(k, 1);
}
damageactor(plr, movestat, i);
}
break;
case 2: // fall
spr.zvel += TICSPERFRAME << 4;
movestat = (short)movesprite(i, ((sintable[(spr.ang + 512) & 2047]) * TICSPERFRAME) << 1,
((sintable[spr.ang]) * TICSPERFRAME) << 1, spr.zvel, 4 << 8, 4 << 8, 0);
spr.lotag -= TICSPERFRAME;
if (zr_florz <= spr.z && spr.lotag < 0) {
spr.z = zr_florz;
changespritestat(i, LAND);
}
break;
case 3: // jumpup
spr.zvel -= TICSPERFRAME << 4;
movestat = (short)movesprite(i, ((sintable[(spr.ang + 512) & 2047]) * TICSPERFRAME) << 3,
((sintable[spr.ang]) * TICSPERFRAME) << 3, spr.zvel, 4 << 8, 4 << 8, 0);
spr.lotag -= TICSPERFRAME;
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag < 0) {
spr.extra = 2;
spr.lotag = 20;
}
break;
}
}
}
static short searchpatrol(SPRITE& spr) {
long mindist = 0x7fffffff;
short target = -1;
short j = headspritestat[APATROLPOINT];
while (j != -1) {
short nextj = nextspritestat[j];
SPRITE tspr = sprite[j];
long dist = klabs(tspr.x - spr.x) + klabs(tspr.y - spr.y);
if (dist < mindist) {
mindist = dist;
target = j;
}
j = nextj;
}
return target;
}
static boolean patrolprocess(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short target = searchpatrol(spr);
if (target != -1) {
SPRITE tspr = sprite[target];
if (cansee(tspr.x, tspr.y, tspr.z, tspr.sectnum, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum)) {
spr.ang = getangle(tspr.x - spr.x, tspr.y - spr.y);
newstatus(i, PATROL);
}
}
return target != -1;
}
static void gonzopike(short s, PLAYER& plr) {
int j = insertsprite(sprite[s].sectnum, JAVLIN);
if (j == -1)
return;
SPRITE& spr = sprite[j];
spr.x = sprite[s].x;
spr.y = sprite[s].y;
spr.z = sprite[s].z - (40 << 8);
spr.cstat = 21;
spr.picnum = THROWPIKE;
spr.ang = (short)(((sprite[s].ang + 2048 + 96) - 512) & 2047);
spr.xrepeat = 24;
spr.yrepeat = 24;
spr.clipdist = 32;
spr.extra = sprite[s].ang;
spr.shade = -15;
spr.xvel = (short)((krand() & 256) - 128);
spr.yvel = (short)((krand() & 256) - 128);
spr.zvel = (short)(((plr.z + (8 << 8) - sprite[s].z) << 7) / engine
.ksqrt((plr.x - sprite[s].x) * (plr.x - sprite[s].x) + (plr.y - sprite[s].y) * (plr.y - sprite[s].y)));
spr.zvel += ((krand() % 256) - 128);
spr.owner = s;
spr.lotag = 1024;
spr.hitag = 0;
spr.pal = 0;
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createGonzoAI() {
auto &e = enemy[GONZOTYPE];
e.info.Init(35, 35, 1024 + 256, 120, 0, 48, false, 50, 0);
e.info.getAttackDist = [](EnemyInfo& e, SPRITE& spr)
{
int out = e.attackdist;
switch (spr.picnum) {
case KURTAT:
case GONZOCSW:
case GONZOCSWAT:
if (spr.extra > 10)
out = 2048 << 1;
break;
}
return out;
};
e.info.getHealth = [](EnemyInfo& e, SPRITE& spr)
{
switch (spr.picnum) {
case KURTAT:
return 10;
case KURTPUNCH:
return adjusthp(15);
case GONZOGSW:
return adjusthp(100);
case GONZOGHM:
return adjusthp(40);
}
return adjusthp(e.health);
};
e.chase = chase;
e.resurect = resurect;
e.skirmish = skirmish;
e.search = search;
e.nuked = nuked;
e.frozen = frozen;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die = die;
}
void premapGonzo(short i) {
SPRITE& spr = sprite[i];
spr.detail = GONZOTYPE;
enemy[GONZOTYPE].info.set(spr);
changespritestat(i, FACE);
switch (spr.picnum) {
case KURTAT:
spr.picnum = GONZOCSW;
break;
case KURTPUNCH:
spr.extra = 0;
spr.picnum = GONZOCSW;
break;
case GONZOCSW:
spr.extra = 20;
break;
case GONZOGSW:
case GONZOGHM:
case GONZOGSH:
spr.clipdist = 32;
spr.extra = 0;
break;
}
}
void deaddude(short sn) {
int j = insertsprite(sprite[sn].sectnum, DEAD);
sprite[j].x = sprite[sn].x;
sprite[j].y = sprite[sn].y;
sprite[j].z = sprite[sn].z;
sprite[j].cstat = 0;
sprite[j].picnum = GONZOBSHDEAD;
sprite[j].shade = sector[sprite[sn].sectnum].floorshade;
sprite[j].pal = 0;
sprite[j].xrepeat = sprite[sn].xrepeat;
sprite[j].yrepeat = sprite[sn].yrepeat;
sprite[j].owner = 0;
sprite[j].lotag = 0;
sprite[j].hitag = 0;
}
END_WH_NS

View file

@ -0,0 +1,529 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void throwhalberd(int s);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (spr.picnum == GRONSW) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
}
else {
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))// && invisibletime < 0)
newstatus(i, ATTACK);
}
else {
checksight(plr, i);
if (!checkdist(plr, i)) {
if ((aimove(i) & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, FLEE); // NEW
}
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
switch (krand() % 3) {
case 0:
sprite[i].picnum = GRONHAL;
sprite[i].hitag = (short)adjusthp(120);
sprite[i].extra = 3;
break;
case 1:
sprite[i].picnum = GRONSW;
sprite[i].hitag = (short)adjusthp(120);
sprite[i].extra = 0;
break;
case 2:
sprite[i].picnum = GRONMU;
sprite[i].hitag = (short)adjusthp(120);
sprite[i].extra = 2;
break;
}
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
return;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == GRONCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
if (sprite[i].picnum == GRONHALDIE)
sprite[i].picnum = GRONHAL;
else if (sprite[i].picnum == GRONSWDIE)
sprite[i].picnum = GRONSW;
else if (sprite[i].picnum == GRONMUDIE)
sprite[i].picnum = GRONMU;
newstatus(i, FACE);
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (sprite[i].picnum == GRONHALPAIN)
sprite[i].picnum = GRONHAL;
else if (sprite[i].picnum == GRONSWPAIN)
sprite[i].picnum = GRONSW;
else if (sprite[i].picnum == GRONMUPAIN)
sprite[i].picnum = GRONMU;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (spr.picnum == GRONSWATTACK) {
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag == 31) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
}
else {
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
spr.z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
spr.ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
}
checksector6(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (spr.picnum == GRONHALATTACK) {
spr.extra--;
playsound_loc(S_THROWPIKE, sprite[i].x, sprite[i].y);
throwhalberd(i);
newstatus(i, CHASE);
}
else if (spr.picnum == GRONMUATTACK) {
spr.extra--;
playsound_loc(S_SPELL2, sprite[i].x, sprite[i].y);
castspell(plr, i);
newstatus(i, CHASE);
}
}
checksector6(i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.picnum == GRONSWDIE || spr.picnum == GRONHALDIE || spr.picnum == GRONMUDIE)
{
if (spr.lotag < 0) {
spr.picnum = GRONDIE;
spr.lotag = 20;
}
else
return;
}
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == GRONDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
static void throwhalberd(int s) {
int j = insertsprite(sprite[s].sectnum, JAVLIN);
if (j == -1)
return;
SPRITE& spr = sprite[j];
spr.x = sprite[s].x;
spr.y = sprite[s].y;
spr.z = sprite[s].z - (40 << 8);
spr.cstat = 17;
spr.picnum = THROWHALBERD;
spr.detail = THROWHALBERDTYPE;
spr.ang = (short)(((sprite[s].ang + 2048) - 512) & 2047);
spr.xrepeat = 8;
spr.yrepeat = 16;
spr.clipdist = 32;
spr.extra = sprite[s].ang;
spr.shade = -15;
spr.xvel = (short)((krand() & 256) - 128);
spr.yvel = (short)((krand() & 256) - 128);
spr.zvel = (short)((krand() & 256) - 128);
spr.owner = (short)s;
spr.lotag = 0;
spr.hitag = 0;
spr.pal = 0;
spr.cstat = 0;
int daz = (((spr.zvel) * TICSPERFRAME) >> 3);
movesprite((short)j, ((sintable[(spr.extra + 512) & 2047]) * TICSPERFRAME) << 7,
((sintable[spr.extra & 2047]) * TICSPERFRAME) << 7, daz, 4 << 8, 4 << 8, 1);
spr.cstat = 21;
}
void createGronAI() {
auto& e = enemy[GRONTYPE];
e.info.Init(game.WH2 ? 35 : 30, game.WH2 ? 35 : 30, -1, 120, 0, 64, false, 300, 0);
e.info.getAttackDist = [](EnemyInfo& e, SPRITE& spr)
{
int out = e.attackdist;
int pic = spr.picnum;
if (pic == GRONHAL || pic == GRONHALATTACK)
out = 1024 + 512;
else if (pic == GRONMU || pic == GRONMUATTACK)
out = 2048;
else if (pic == GRONSW || pic == GRONSWATTACK)
out = 1024 + 256;
return out;
};
e.info.getHealth = [](EnemyInfo& e, SPRITE& spr)
{
if (game.WH2) {
if (spr.picnum == GRONHAL)
return adjusthp(65);
if (spr.picnum == GRONMU)
return adjusthp(70);
}
return adjusthp(e.health);
};
e.chase = chase;
e.resurect = resurect;
e.skirmish = skirmish;
e.search = search;
e.nuked = nuked;
e.frozen = frozen;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die = die;
}
void premapGron(short i) {
SPRITE& spr = sprite[i];
if (spr.picnum == GRONSW && spr.pal == 10)
deletesprite(i);
spr.detail = GRONTYPE;
enemy[GRONTYPE].info.set(spr);
changespritestat(i, FACE);
if (spr.picnum == GRONHAL)
spr.extra = 4;
else if (spr.picnum == GRONSW)
spr.extra = 0;
else if (spr.picnum == GRONMU)
spr.extra = 2;
}
END_WH_NS

View file

@ -0,0 +1,249 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (plr.z < spr.z)
spr.z -= TICSPERFRAME << 8;
if (plr.z > spr.z)
spr.z += TICSPERFRAME << 8;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum) && plr.invisibletime < 0)
newstatus(i, ATTACK);
return;
}
else {
int dax = (sintable[(sprite[i].ang + 512) & 2047] * TICSPERFRAME) << 3;
int day = (sintable[sprite[i].ang & 2047] * TICSPERFRAME) << 3;
checksight(plr, i);
if (totalclock % 100 > 70)
trailingsmoke(i, true);
if (!checkdist(plr, i)) {
checkmove(i, dax, day);
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, CHASE); // NEW
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, true);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if (!isValidSector(spr.sectnum))
return;
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
return;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == GUARDIANCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (plr.z < spr.z) {
spr.z -= TICSPERFRAME << 8;
}
if (plr.z > spr.z) {
spr.z += TICSPERFRAME << 8;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, true);
checksector6(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
if (totalclock % 100 > 70)
trailingsmoke(i, true);
int movestat = aifly(i);
if (movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, true);
setsprite(i, spr.x, spr.y, spr.z);
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = GUARDIAN;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
// aifly(i);
// setsprite(i, spr.x, spr.y, spr.z);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (plr.z < spr.z) {
spr.z -= TICSPERFRAME << 8;
}
if (plr.z > spr.z) {
spr.z += TICSPERFRAME << 8;
}
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == GUARDIANATTACK + 6) {
spr.picnum = GUARDIAN;
playsound_loc(S_FIREBALL, sprite[i].x, sprite[i].y);
castspell(plr, i);
newstatus(i, CHASE);
}
checksector6(i);
}
void createGuardianAI() {
auto& e = enemy[GUARDIANTYPE];
e.info.Init(game.WH2 ? 35 : 32, game.WH2 ? 35 : 32, 4096, 120, 0, 64, true, game.WH2 ? 100 : 200, 0);
e.chase = chase;
e.nuked = nuked;
e.attack = attack;
e.face = face;
e.search = search;
e.flee = flee;
e.pain = pain;
e.cast = cast;
}
void premapGuardian(short i) {
SPRITE& spr = sprite[i];
spr.detail = GUARDIANTYPE;
enemy[GUARDIANTYPE].info.set(spr);
changespritestat(i, FACE);
}
END_WH_NS

View file

@ -0,0 +1,340 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = IMP;
newstatus(i, FACE);
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = IMP;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == IMPDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = IMP;
spr.hitag = (short)adjusthp(20);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag == 32) { //original 64
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createImpAI() {
auto &e = enemy[IMPTYPE];
e.info.Init(25, 25, 1024, 120, 0, 64, false, 20, 0);
e.chase = chase;
e.frozen = frozen;
e.pain = pain;
e.die = die;
e.nuked = nuked;
e.resurect = resurect;
e.face = face;
e.flee = flee;
e.attack = attack;
e.search = search;
e.skirmish = skirmish;
}
void premapImp(short i) {
SPRITE& spr = sprite[i];
spr.detail = IMPTYPE;
enemy[IMPTYPE].info.set(spr);
changespritestat(i, FACE);
spr.shade = -4;
}
}
END_WH_NS

View file

@ -0,0 +1,423 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void spawnabaddy(int i, int monster);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (mapon < 24) {
sprite[i].extra -= TICSPERFRAME;
if (sprite[i].extra < 0) {
for (int j = 0; j < 8; j++)
trailingsmoke(i, true);
deletesprite((short)i);
return;
}
}
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))// && invisibletime < 0)
newstatus(i, ATTACK);
}
else {
checksight(plr, i);
if (!checkdist(i, plr.x, plr.y, plr.z)) {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, FLEE); // NEW
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = JUDY;
spr.hitag = (short)adjusthp(200);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == JUDYCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = JUDY;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(i, plr.x, plr.y, plr.z))
newstatus(i, ATTACK);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
sprite[i].extra -= TICSPERFRAME;
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == JUDYATTACK1 + 3) {
sprite[i].picnum = JUDYATTACK1;
playsound_loc(S_JUDY1 + krand() % 4, sprite[i].x, sprite[i].y);
if (krand() % 100 > 70) {
castspell(plr, i);
}
else {
if (krand() % 100 > 40) {
// raise the dead
short j = headspritestat[DEAD];
while (j >= 0) {
short nextj = nextspritestat[j];
sprite[j].lotag = (short)((krand() % 120) + 120);
kills--;
newstatus(j, RESURECT);
j = nextj;
}
}
else {
if (krand() % 100 > 50) {
// curse
for (int j = 1; j < 9; j++) {
plr.ammo[j] = 3;
}
}
else {
int j = krand() % 5;
switch (j) {
case 0:// SPAWN WILLOW
spawnabaddy(i, WILLOW);
break;
case 1:// SPAWN 10 SPIDERS
for (j = 0; j < 4; j++) {
spawnabaddy(i, SPIDER);
}
break;
case 2:// SPAWN 2 GRONSW
for (j = 0; j < 2; j++) {
spawnabaddy(i, GRONSW);
}
break;
case 3:// SPAWN SKELETONS
for (j = 0; j < 4; j++) {
spawnabaddy(i, SKELETON);
}
break;
case 4:
castspell(plr, i);
break;
}
}
}
}
newstatus(i, CHASE);
}
else if (spr.picnum == JUDYATTACK2 + 8) {
sprite[i].picnum = JUDYATTACK2;
playsound_loc(S_JUDY1 + krand() % 4, sprite[i].x, sprite[i].y);
if (krand() % 100 > 50)
skullycastspell(plr, i);
else {
if (krand() % 100 > 70) {
if (krand() % 100 > 50) {
plr.health = 0;
addhealth(plr, 1);
}
else {
addarmor(plr, -(plr.armor));
plr.armortype = 0;
}
}
else {
int j = krand() % 5;
switch (j) {
case 0:// SPAWN WILLOW
spawnabaddy(i, WILLOW);
break;
case 1:// SPAWN 6 SPIDERS
for (j = 0; j < 4; j++) {
spawnabaddy(i, SPIDER);
}
break;
case 2:// SPAWN 2 GRONSW
for (j = 0; j < 2; j++) {
spawnabaddy(i, GRONSW);
}
break;
case 3:// SPAWN SKELETONS
for (j = 0; j < 4; j++) {
spawnabaddy(i, SKELETON);
}
break;
case 4:
castspell(plr, i);
break;
}
}
}
newstatus(i, CHASE);
}
checksector6(i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == JUDYDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
void judyOperate(PLAYER& plr)
{
short nextsprite;
for (short i = headspritestat[WITCHSIT]; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
sprite[i].ang = (short)(getangle(plr.x - sprite[i].x, plr.y - sprite[i].y) & 2047);
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum)) {
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
sprite[i].picnum++;
sprite[i].lotag = 12;
if (sprite[i].picnum == JUDYSIT + 4) {
sprite[i].picnum = JUDY;
newstatus(i, FACE);
}
}
}
}
}
static void spawnabaddy(int i, int monster) {
short j = insertsprite(sprite[i].sectnum, FACE);
sprite[j].x = sprite[i].x + (krand() & 2048) - 1024;
sprite[j].y = sprite[i].y + (krand() & 2048) - 1024;
sprite[j].z = sprite[i].z;
sprite[j].pal = 0;
sprite[j].shade = 0;
sprite[j].cstat = 0;
if(monster == WILLOW)
premapWillow(j);
else if(monster == SPIDER)
premapSpider(j);
else if(monster == GRONSW)
premapGron(j);
else if(monster == SKELETON)
premapSkeleton(j);
else if(monster == GONZOGSH)
premapGonzo(j);
sprite[j].picnum = (short) monster;
killcnt++;
setsprite(j, sprite[j].x, sprite[j].y, sprite[j].z);
//game.pInt.setsprinterpolate(j, sprite[j]);
}
void createJudyAI() {
auto &e = enemy[JUDYTYPE];
e.info.Init(32, 32, 2048, 120, 0, 64, false, 500, 0);
e.chase = chase;
e.resurect = resurect;
e.search = search;
e.nuked = nuked;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die = die;
}
void premapJudy(short i) {
SPRITE& spr = sprite[i];
spr.detail = JUDYTYPE;
enemy[JUDYTYPE].info.set(spr);
if (mapon > 24)
spr.hitag = adjusthp(700);
if (spr.picnum == JUDYSIT) {
changespritestat(i, WITCHSIT);
spr.extra = 1200;
} else
changespritestat(i, FACE);
}
}
END_WH_NS

View file

@ -0,0 +1,284 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))// && invisibletime < 0)
newstatus(i, ATTACK);
}
else {
checksight(plr, i);
if (!checkdist(i, plr.x, plr.y, plr.z)) {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, FLEE); // NEW
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = KATIE;
spr.hitag = (short)adjusthp(200);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = KATIE;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(i, plr.x, plr.y, plr.z))
newstatus(i, ATTACK);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == KATIEAT + 2) {
if (spr.extra >= 2) {
if (rand() % 100 > 50) {
for (int j = 0; j < 4; j++) {
spawnabaddy(i, GONZOGSH);
}
}
else {
for (int j = 0; j < 6; j++) {
spawnabaddy(i, GRONSW);
}
}
spr.picnum = KATIE;
spr.extra--;
playsound_loc(S_FIREBALL, spr.x, spr.y);
newstatus(i, CHASE);
}
}
if (spr.picnum == KATIEAT + 6) {
if (spr.extra == 1) {
for (short j = 0; j < MAXSPRITES; j++) {
if (sprite[j].pal == 8) {
sprite[j].picnum--;
sprite[j].pal = 0;
sprite[j].shade = 0;
changespritestat(j, FACE);
}
}
spr.picnum = KATIE;
playsound_loc(S_FIREBALL, spr.x, spr.y);
newstatus(i, CHASE);
spr.extra--;
}
}
if (spr.picnum == KATIEAT + 16) {
spr.picnum = KATIE;
playsound_loc(S_FIREBALL, spr.x, spr.y);
castspell(plr, i);
newstatus(i, CHASE);
spr.extra++;
}
checksector6(i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == KATIEDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
void createKatieAI() {
auto& e = enemy[KATIETYPE];
e.info.Init(35, 35, 2048, 120, 0, 64, false, 200, 0);
e.chase = chase;
e.resurect = resurect;
e.search = search;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die = die;
}
void premapKatie(short i) {
SPRITE& spr = sprite[i];
spr.detail = KATIETYPE;
changespritestat(i, FACE);
enemy[KATIETYPE].info.set(spr);
spr.extra = 5;
}
END_WH_NS

View file

@ -0,0 +1,363 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
if ((krand() % 100) > 98)
playsound_loc(S_KSNARL1 + (krand() % 4), sprite[i].x, sprite[i].y);
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == KOBOLDDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = KOBOLD;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit))
{
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag == 34) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = KOBOLD;
spr.hitag = (short)adjusthp(30);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
if ((krand() % 100) > 98)
playsound_loc(S_KSNARL1 + (krand() % 4), sprite[i].x, sprite[i].y);
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = KOBOLD;
newstatus(i, FACE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
return;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == KOBOLDCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createKoboldAI() {
auto& e = enemy[KOBOLDTYPE];
e.info.Init(game.WH2 ? 60 : 54, game.WH2 ? 60 : 54, 1024, 120, 0, 64, false, 20, 0);
e.chase = chase;
e.die = die;
e.pain = pain;
e.face = face;
e.flee = flee;
e.attack = attack;
e.resurect = resurect;
e.search = search;
e.frozen = frozen;
e.nuked = nuked;
e.skirmish = skirmish;
}
void premapKobold(short i) {
SPRITE& spr = sprite[i];
spr.detail = KOBOLDTYPE;
enemy[KOBOLDTYPE].info.set(spr);
changespritestat(i, FACE);
if (spr.pal == 8)
spr.hitag = adjusthp(40);
else if (spr.pal == 7)
spr.hitag = adjusthp(60);
}
END_WH_NS

View file

@ -0,0 +1,103 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void stand(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (sintable[(spr.ang + 512) & 2047] * (plr.x - spr.x)
+ sintable[spr.ang & 2047] * (plr.y - spr.y) >= 0)
if (cansee(spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7), spr.sectnum, plr.x, plr.y,
plr.z, plr.sector) && plr.invisibletime < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus(i, DIE);
}
static void kurtExplo(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
spr.picnum++;
if (spr.lotag < 0)
spr.lotag = 12;
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].detail == KURTTYPE) {
sprite[j].hitag -= TICSPERFRAME << 4;
if (sprite[j].hitag < 0) {
newstatus(j, DIE);
}
}
}
j = nextj;
}
}
void createKurtAI() {
auto& e = enemy[KURTTYPE];
e.info.Init(35, 35, 1024 + 256, 120, 0, 48, false, 50, 0);
e.info.getAttackDist = [](EnemyInfo& e, SPRITE& spr) {
int out = e.attackdist;
switch (spr.picnum) {
case KURTAT:
case GONZOCSW:
case GONZOCSWAT:
if (spr.extra > 10)
out = 2048 << 1;
break;
}
return out;
};
e.stand = stand;
e.nuked = nuked;
e.chase = enemy[GONZOTYPE].chase;
e.resurect = enemy[GONZOTYPE].resurect;
e.skirmish = enemy[GONZOTYPE].skirmish;
e.search = enemy[GONZOTYPE].search;
e.frozen = enemy[GONZOTYPE].frozen;
e.pain = enemy[GONZOTYPE].pain;
e.face = enemy[GONZOTYPE].face;
e.attack = enemy[GONZOTYPE].attack;
e.cast = enemy[GONZOTYPE].cast;
e.flee = enemy[GONZOTYPE].flee;
e.die = enemy[GONZOTYPE].die;
}
void premapKurt(short i) {
SPRITE& spr = sprite[i];
spr.detail = KURTTYPE;
enemy[KURTTYPE].info.set(spr);
changespritestat(i, STAND);
switch (spr.picnum) {
case KURTSTAND:
spr.extra = 20;
break;
case KURTKNEE:
spr.extra = 10;
break;
}
}
END_WH_NS

View file

@ -0,0 +1,362 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = MINOTAUR;
spr.hitag = (short)adjusthp(100);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
return;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == MINOTAURCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = MINOTAUR;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag == 31) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == MINOTAURDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = MINOTAUR;
newstatus(i, FACE);
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createMinotaurAI() {
//picanm[MINOTAUR + 16] = 0;
auto& e = enemy[MINOTAURTYPE];
e.info.Init(64, 64, 1024 + 512, 120, 0, 64, false, game.WH2 ? 80 : 100, 0);
e.chase = chase;
e.resurect = resurect;
e.skirmish = skirmish;
e.nuked = nuked;
e.pain = pain;
e.face = face;
e.attack = attack;
e.die = die;
e.flee = flee;
e.frozen = frozen;
e.search = search;
}
void premapMinotaur(short i) {
SPRITE& spr = sprite[i];
spr.detail = MINOTAURTYPE;
enemy[MINOTAURTYPE].info.set(spr);
changespritestat(i, FACE);
if (krand() % 100 > 50)
spr.extra = 1;
}
END_WH_NS

View file

@ -0,0 +1,479 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void newguyarrow(short s, PLAYER& plr);
static void stand(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (sintable[(spr.ang + 512) & 2047] * (plr.x - spr.x)
+ sintable[spr.ang & 2047] * (plr.y - spr.y) >= 0)
if (cansee(spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7), spr.sectnum, plr.x, plr.y,
plr.z, plr.sector) && plr.invisibletime < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
}
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
int j = krand() % 3;
switch (j) {
case 0:
spr.extra = 30;
spr.hitag = (short)adjusthp(85);
break;
case 1:
spr.extra = 20;
spr.hitag = (short)adjusthp(85);
break;
case 2:
spr.extra = 10;
spr.hitag = (short)adjusthp(45);
break;
case 3:
spr.extra = 0;
spr.hitag = (short)adjusthp(15);
break;
}
spr.xrepeat = 35;
spr.yrepeat = 35;
spr.picnum = NEWGUY;
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checksector6(i);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = NEWGUY;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
if (plr.invisibletime < 0)
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
switch (spr.picnum) {
case NEWGUYCAST:
case NEWGUYBOW:
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
break;
case NEWGUYMACE:
case NEWGUYPUNCH:
if (spr.lotag == 31) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
break;
}
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == NEWGUYDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == NEWGUYCAST + 2) {
spr.extra--;
spr.picnum = NEWGUY;
playsound_loc(S_WISP, sprite[i].x, sprite[i].y);
skullycastspell(plr, i);
newstatus(i, CHASE);
}
if (spr.picnum == NEWGUYBOW + 2) {
spr.extra--;
spr.picnum = NEWGUY;
playsound_loc(S_PLRWEAPON3, sprite[i].x, sprite[i].y);
newguyarrow(i, plr);
newstatus(i, CHASE);
}
checksector6(i);
}
static void newguyarrow(short s, PLAYER& plr) {
int j = insertsprite(sprite[s].sectnum, JAVLIN);
if (j == -1)
return;
SPRITE& spr = sprite[j];
spr.x = sprite[s].x;
spr.y = sprite[s].y;
spr.z = sprite[s].z - (40 << 8);
spr.cstat = 21;
spr.picnum = WALLARROW;
spr.ang = (short)(((sprite[s].ang + 2048 + 96) - 512) & 2047);
spr.xrepeat = 24;
spr.yrepeat = 24;
spr.clipdist = 32;
spr.extra = sprite[s].ang;
spr.shade = -15;
spr.xvel = (short)((krand() & 256) - 128);
spr.yvel = (short)((krand() & 256) - 128);
spr.zvel = (short)(((plr.z + (8 << 8) - sprite[s].z) << 7) / engine
.ksqrt((plr.x - sprite[s].x) * (plr.x - sprite[s].x) + (plr.y - sprite[s].y) * (plr.y - sprite[s].y)));
spr.zvel += ((krand() % 256) - 128);
spr.owner = s;
spr.lotag = 1024;
spr.hitag = 0;
spr.pal = 0;
}
void createNewGuyAI() {
//picanm[NEWGUYDIE] = 0;
//picanm[NEWGUYDIE + 3] = 0;
auto& e = enemy[NEWGUYTYPE];
e.info.Init(35, 35, 1024 + 256, 120, 0, 48, false, 90, 0);
e.info.getAttackDist = [](EnemyInfo& e, SPRITE& spr)
{
int out = e.attackdist;
switch (spr.picnum) {
case NEWGUY:
case NEWGUYMACE:
case NEWGUYCAST:
case NEWGUYBOW:
if (spr.extra > 10)
out = 2048 << 1;
else out = 1024 + 256;
break;
case NEWGUYPUNCH:
out = 1024 + 256;
break;
default:
out = 512;
break;
}
return out;
};
e.info.getHealth = [](EnemyInfo& e, SPRITE& spr)
{
switch (spr.picnum) {
case NEWGUYSTAND:
case NEWGUYKNEE:
return adjusthp(50);
case NEWGUYCAST:
return adjusthp(85);
case NEWGUYBOW:
return adjusthp(85);
case NEWGUYMACE:
return adjusthp(45);
case NEWGUYPUNCH:
return adjusthp(15);
}
return adjusthp(e.health);
};
e.stand = stand;
e.chase = chase;
e.resurect = resurect;
e.skirmish = skirmish;
e.search = search;
e.nuked = nuked;
e.pain = pain;
e.face = face;
e.flee = flee;
e.attack = attack;
e.die = die;
e.cast = cast;
}
void premapNewGuy(short i) {
SPRITE& spr = sprite[i];
spr.detail = NEWGUYTYPE;
enemy[NEWGUYTYPE].info.set(spr);
switch (spr.picnum) {
case NEWGUYSTAND:
case NEWGUYKNEE:
changespritestat(i, STAND);
if (spr.picnum == NEWGUYSTAND)
spr.extra = 20;
else
spr.extra = 30;
break;
case NEWGUYCAST:
case NEWGUYBOW:
case NEWGUYMACE:
case NEWGUYPUNCH:
case NEWGUY:
switch (spr.picnum) {
case NEWGUYCAST:
spr.extra = 30;
break;
case NEWGUYBOW:
spr.extra = 20;
break;
case NEWGUYMACE:
spr.extra = 10;
break;
case NEWGUYPUNCH:
spr.extra = 0;
break;
}
changespritestat(i, FACE);
spr.picnum = NEWGUY;
}
}
}
END_WH_NS

View file

@ -0,0 +1,111 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
newstatus(i, FLEE);
}
static void search(PLAYER& plr, short i) {
sprite[i].ang = (short) (((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047);
newstatus(i, FLEE);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
spr.ang = (short) (((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
spr.owner = sprite[plr.spritenum].owner;
newstatus(i, FLEE);
}
static void die(PLAYER& plr, short i) {
deletesprite(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
return;
}
if ((movestat & kHitTypeMask) == kHitWall) {
WALL wal = wall[movestat & kHitIndexMask];
short wallang = (short)((getangle(wall[wal.point2].x - wal.x, wall[wal.point2].y - wal.y) + 512)
& 2047);
spr.ang = (short)(krand() & 512 - 256 + wallang);
}
if ((movestat & kHitTypeMask) == kHitSprite) {
SPRITE sp = sprite[movestat & kHitIndexMask];
spr.owner = (short)(movestat & kHitIndexMask);
spr.ang = getangle(sp.x - spr.x, sp.y - spr.y);
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
}
if (klabs(plr.x - spr.x) <= 1024 && klabs(plr.y - spr.y) <= 1024) {
spr.owner = sprite[plr.spritenum].owner;
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
// switch (checkfluid(i, zr_florhit)) {
// case TYPELAVA:
// case TYPEWATER:
// spr.z += tilesizy[spr.picnum] << 5;
// break;
// }
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA2
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
void createRatAI() {
auto& e = enemy[RATTYPE];
e.info.Init(32, 32, 512, 120, 0, 32, false, 0, 0);
e.info.getHealth = [](EnemyInfo&, SPRITE& spr)
{
return 10;
};
e.chase = chase;
e.search = search;
e.face = face;
e.die = die;
e.flee = flee;
}
void premapRat(short i) {
SPRITE& spr = sprite[i];
spr.detail = RATTYPE;
enemy[RATTYPE].info.set(spr);
changespritestat(i, FACE);
spr.shade = 12;
spr.pal = 5;
}
END_WH_NS

View file

@ -0,0 +1,388 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == SKELETONDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.picnum = SKELETON;
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void stand(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (sintable[(spr.ang + 2560) & 2047] * (plr.x - spr.x)
+ sintable[(spr.ang + 2048) & 2047] * (plr.y - spr.y) >= 0)
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (spr.picnum == HANGMAN) {
newstatus(i, CHILL);
playsound_loc(S_SKELSEE, spr.x, spr.y);
}
else {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
}
checksector6(i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (spr.lotag == 16) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = SKELETON;
spr.hitag = (short)adjusthp(10);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = SKELETON;
newstatus(i, FACE);
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
return;
}
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == SKELETONCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
void skeletonChill(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 18;
if (spr.picnum == HANGMAN + 10) {
spr.picnum = SKELETON;
newstatus(i, FACE);
}
}
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
int dx = klabs(spr.x - sprite[j].x); // x distance to sprite
int dy = klabs(spr.y - sprite[j].y); // y distance to sprite
int dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
int dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createSkeletonAI() {
auto& e = enemy[SKELETONTYPE];
e.info.Init(game.WH2 ? 35 : 24, game.WH2 ? 35 : 24, 1024, 120, 0, 64, false, game.WH2 ? 25 : 30, 0);
e.chase = chase;
e.die = die;
e.face = face;
e.flee = flee;
e.stand = stand;
e.attack = attack;
e.resurect = resurect;
e.search = search;
e.frozen = frozen;
e.nuked = nuked;
e.skirmish = skirmish;
}
void premapSkeleton(short i) {
SPRITE& spr = sprite[i];
spr.detail = SKELETONTYPE;
enemy[SKELETONTYPE].info.set(spr);
if (spr.picnum == HANGMAN) {
spr.xrepeat = 28;
spr.yrepeat = 28;
changespritestat(i, STAND);
return;
}
changespritestat(i, FACE);
}
END_WH_NS

View file

@ -0,0 +1,258 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))// && invisibletime < 0)
newstatus(i, ATTACK);
}
else {
checksight(plr, i);
if (!checkdist(plr, i)) {
if ((aimove(i) & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, FLEE); // NEW
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = SKULLY;
spr.hitag = (short)adjusthp(100);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
checksector6(i);
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 24;
if (spr.picnum == SKULLYCHAR + 4) {
trailingsmoke(i, false);
deletesprite(i);
}
}
}
static void pain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum = SKULLY;
spr.ang = (short)plr.ang;
newstatus(i, FLEE);
}
aimove(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
case TYPEWATER:
spr.z += tilesizy[spr.picnum] << 5;
break;
}
setsprite(i, spr.x, spr.y, spr.z);
sprite[i].lotag -= TICSPERFRAME;
if (sprite[i].lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum))
newstatus(i, CAST);
else
newstatus(i, CHASE);
}
else
sprite[i].ang = getangle(plr.x - sprite[i].x, plr.y - sprite[i].y);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
}
static void cast(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.picnum++;
spr.lotag = 12;
}
if (spr.picnum == SKULLYATTACK + 2) {
sprite[i].picnum = SKULLY;
playsound_loc(S_SKULLWITCH1 + krand() % 3, sprite[i].x, sprite[i].y);
skullycastspell(plr, i);
newstatus(i, CHASE);
}
checksector6(i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == SKULLYDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
void createSkullyAI() {
auto& e = enemy[SKULLYTYPE];
e.info.Init(32, 32, 2048, 120, 0, 64, false, 300, 0);
e.chase = chase;
e.resurect = resurect;
e.search = search;
e.nuked = nuked;
e.pain = pain;
e.face = face;
e.attack = attack;
e.flee = flee;
e.cast = cast;
e.die = die;
}
void premapSkully(short i) {
SPRITE& spr = sprite[i];
spr.detail = SKULLYTYPE;
enemy[SKULLYTYPE].info.set(spr);
changespritestat(i, FACE);
if (krand() % 100 > 50)
spr.extra = 1;
}
END_WH_NS

View file

@ -0,0 +1,322 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void checkexpl(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
if (checkdist(plr, i)) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, ATTACK);
}
else if (krand() % 63 > 60) {
spr.ang = (short)(((krand() & 128 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
int movestat = aimove(i);
if ((movestat & kHitTypeMask) == kHitFloor)
{
spr.ang = (short)((spr.ang + 1024) & 2047);
newstatus(i, FLEE);
return;
}
if ((movestat & kHitTypeMask) == kHitSprite) {
if ((movestat & kHitIndexMask) != plr.spritenum) {
short daang = (short)((spr.ang - 256) & 2047);
spr.ang = daang;
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else
newstatus(i, SKIRMISH);
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, SKIRMISH);
}
}
}
}
else {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA2 || sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
checkexpl(plr, i);
}
static void resurect(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
newstatus(i, FACE);
spr.picnum = SPIDER;
spr.hitag = (short)adjusthp(15);
spr.lotag = 100;
spr.cstat |= 1;
}
}
static void skirmish(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
newstatus(i, FACE);
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
if (checksector6(i))
return;
checkexpl(plr, i);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, false);
if (!checksector6(i))
checkexpl(plr, i);
}
static void frozen(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
spr.pal = 0;
spr.picnum = SPIDER;
newstatus(i, FACE);
}
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
boolean cansee = cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum);
if (cansee && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else if (cansee) newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
checkexpl(plr, i);
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
spr.z = zr_florz;
switch (checkfluid(i, zr_florhit)) {
case TYPELAVA:
sprite[i].hitag--;
if (sprite[i].hitag < 0)
newstatus(i, DIE);
break;
}
setsprite(i, spr.x, spr.y, spr.z);
if (spr.lotag >= 64) {
if (checksight(plr, i))
if (checkdist(plr, i)) {
spr.ang = (short)checksight_ang;
attack(plr, i);
if (krand() % 100 > ((plr.lvl * 7) + 20)) {
playsound_loc(S_SPIDERBITE, sprite[i].x, sprite[i].y);
plr.poisoned = 1;
plr.poisontime = 7200;
showmessage("Poisoned", 360);
newstatus(i, DIE);
return;
}
}
}
else if (spr.lotag < 0) {
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047); // NEW
newstatus(i, FLEE);
}
else
newstatus(i, CHASE);
}
spr.lotag -= TICSPERFRAME;
checksector6(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aimove(i);
if ((movestat & kHitTypeMask) != kHitFloor && movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, false);
setsprite(i, spr.x, spr.y, spr.z);
checkexpl(plr, i);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (spr.picnum == SPIDERDEAD) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void checkexpl(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
short j = headspritesect[spr.sectnum];
while (j != -1) {
short nextj = nextspritesect[j];
long dx = klabs(spr.x - sprite[j].x); // x distance to sprite
long dy = klabs(spr.y - sprite[j].y); // y distance to sprite
long dz = klabs((spr.z >> 8) - (sprite[j].z >> 8)); // z distance to sprite
long dh = tilesizy[sprite[j].picnum] >> 1; // height of sprite
if (dx + dy < PICKDISTANCE && dz - dh <= getPickHeight()) {
if (sprite[j].picnum == EXPLO2
|| sprite[j].picnum == SMOKEFX
|| sprite[j].picnum == MONSTERBALL) {
spr.hitag -= TICSPERFRAME << 2;
if (spr.hitag < 0) {
newstatus(i, DIE);
}
}
}
j = nextj;
}
}
void createSpiderAI() {
auto& e = enemy[SPIDERTYPE];
e.info.Init(24, 18, 512, 60, 0, 64, false, 5, 0);
e.chase = chase;
e.resurect = resurect;
e.skirmish = skirmish;
e.search = search;
e.frozen = frozen;
e.face = face;
e.attack = attack;
e.flee = flee;
e.die = die;
}
void premapSpider(short i) {
SPRITE& spr = sprite[i];
spr.detail = SPIDERTYPE;
enemy[SPIDERTYPE].info.set(spr);
changespritestat(i, FACE);
}
END_WH_NS

View file

@ -0,0 +1,291 @@
#include "ns.h"
#include "wh.h"
BEGIN_WH_NS
static void willowDrain(PLAYER& plr, short i);
static void chase(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0)
spr.lotag = 250;
short osectnum = spr.sectnum;
if (krand() % 63 == 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, sprite[i].x, sprite[i].y,
sprite[i].z - (tilesizy[sprite[i].picnum] << 7), sprite[i].sectnum) && plr.invisibletime < 0)
newstatus(i, ATTACK);
return;
}
else {
//sprite[i].z = sector[sprite[i].sectnum].floorz - (32 << 8);
int dax = (sintable[(sprite[i].ang + 512) & 2047] * TICSPERFRAME) << 3;
int day = (sintable[sprite[i].ang & 2047] * TICSPERFRAME) << 3;
checksight(plr, i);
if (!checkdist(plr, i)) {
checkmove(i, dax, day);
}
else {
if (krand() % 8 == 0) // NEW
newstatus(i, ATTACK); // NEW
else { // NEW
sprite[i].ang = (short)(((krand() & 512 - 256) + sprite[i].ang + 1024) & 2047); // NEW
newstatus(i, CHASE); // NEW
}
}
}
getzrange(spr.x, spr.y, spr.z - 1, spr.sectnum, (spr.clipdist) << 2, CLIPMASK0);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (spr.z > zr_florz)
spr.z = zr_florz;
if (spr.z < zr_ceilz - (32 << 8))
spr.z = zr_ceilz - (32 << 8);
if (checksector6(i))
return;
processfluid(i, zr_florhit, true);
if (sector[osectnum].lotag == KILLSECTOR) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
setsprite(i, spr.x, spr.y, spr.z);
if ((zr_florhit & kHitTypeMask) == kHitSector && (sector[spr.sectnum].floorpicnum == LAVA
|| sector[spr.sectnum].floorpicnum == LAVA1 || sector[spr.sectnum].floorpicnum == ANILAVA)) {
spr.hitag--;
if (spr.hitag < 0)
newstatus(i, DIE);
}
}
static void attack(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (plr.z < spr.z)
spr.z -= TICSPERFRAME << 8;
if (plr.z > spr.z)
spr.z += TICSPERFRAME << 8;
if (spr.lotag < 0) {
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum))
if (checkdist(plr, i)) {
if (plr.shockme < 0)
if ((krand() & 1) != 0) {
plr.shockme = 120;
if (!game.WH2) {
plr.lvl--;
switch (plr.lvl) {
case 1:
plr.score = 0;
plr.maxhealth = 100;
break;
case 2:
plr.score = 2350;
plr.maxhealth = 120;
break;
case 3:
plr.score = 4550;
plr.maxhealth = 140;
break;
case 4:
plr.score = 9300;
plr.maxhealth = 160;
break;
case 5:
plr.score = 18400;
plr.maxhealth = 180;
break;
case 6:
plr.score = 36700;
plr.maxhealth = 200;
break;
case 7:
plr.score = 75400;
plr.maxhealth = 200;
break;
}
if (plr.lvl < 1) {
plr.lvl = 1;
plr.health = -1;
}
showmessage("Level Drained", 360);
}
else
showmessage("Shocked", 360);
}
}
else
newstatus(i, DRAIN);
else
newstatus(i, CHASE);
}
int floorz = getflorzofslope(spr.sectnum, spr.x, spr.y) - (16 << 8);
if (spr.z > floorz)
spr.z = floorz;
}
static void face(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (cansee(plr.x, plr.y, plr.z, plr.sector, spr.x, spr.y, spr.z - (tilesizy[spr.picnum] << 7),
spr.sectnum) && plr.invisibletime < 0) {
spr.ang = (short)(getangle(plr.x - spr.x, plr.y - spr.y) & 2047);
if (plr.shadowtime > 0) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang + 1024) & 2047);
newstatus(i, FLEE);
}
else {
spr.owner = plr.spritenum;
newstatus(i, CHASE);
}
}
else { // get off the wall
if (spr.owner == plr.spritenum) {
spr.ang = (short)(((krand() & 512 - 256) + spr.ang) & 2047);
newstatus(i, FINDME);
}
else newstatus(i, FLEE);
}
if (checkdist(plr, i))
newstatus(i, ATTACK);
}
static void search(PLAYER& plr, short i) {
aisearch(plr, i, true);
checksector6(i);
}
static void flee(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
short osectnum = spr.sectnum;
int movestat = aifly(i);
if (movestat != 0) {
if ((movestat & kHitTypeMask) == kHitWall) {
int nWall = movestat & kHitIndexMask;
int nx = -(wall[wall[nWall].point2].y - wall[nWall].y) >> 4;
int ny = (wall[wall[nWall].point2].x - wall[nWall].x) >> 4;
spr.ang = getangle(nx, ny);
}
else {
spr.ang = getangle(plr.x - spr.x, plr.y - spr.y);
newstatus(i, FACE);
}
}
if (spr.lotag < 0)
newstatus(i, FACE);
if ((spr.sectnum != osectnum) && (sector[spr.sectnum].lotag == 10))
warpsprite(i);
if (checksector6(i))
return;
processfluid(i, zr_florhit, true);
setsprite(i, spr.x, spr.y, spr.z);
}
static void die(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag <= 0) {
spr.picnum++;
spr.lotag = 20;
if (sprite[i].picnum == WILLOWEXPLO || sprite[i].picnum == WILLOWEXPLO + 1
|| sprite[i].picnum == WILLOWEXPLO + 2)
sprite[i].xrepeat = sprite[i].yrepeat <<= 1;
if (spr.picnum == WILLOWEXPLO + 2) {
if (difficulty == 4)
newstatus(i, RESURECT);
else {
kills++;
newstatus(i, DEAD);
}
}
}
}
static void nuked(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
if (game.WH2) {
chunksofmeat(plr, i, spr.x, spr.y, spr.z, spr.sectnum, spr.ang);
trailingsmoke(i, false);
newstatus((short)i, DIE);
}
}
void willowProcess(PLAYER& plr)
{
for (short i = headspritestat[DRAIN], nextsprite; i >= 0; i = nextsprite) {
nextsprite = nextspritestat[i];
SPRITE& spr = sprite[i];
switch (spr.detail) {
case WILLOWTYPE:
willowDrain(plr, i);
break;
}
}
}
static void willowDrain(PLAYER& plr, short i) {
SPRITE& spr = sprite[i];
spr.lotag -= TICSPERFRAME;
if (spr.lotag < 0) {
playsound_loc(S_FIREBALL, spr.x, spr.y);
int oldz = spr.z;
spr.z += 6144;
castspell(plr, i);
spr.z = oldz;
newstatus(i, CHASE);
}
}
void createWillowAI() {
auto& e = enemy[WILLOWTYPE];
e.info.Init(32, 32, 512, 120, 0, 64, true, game.WH2 ? 5 : 400, 0);
e.chase = chase;
e.attack = attack;
e.face = face;
e.search = search;
e.flee = flee;
e.die = die;
e.nuked = nuked;
}
void premap(short i) {
SPRITE& spr = sprite[i];
spr.detail = WILLOWTYPE;
enemy[WILLOWTYPE].info.set(spr);
spr.cstat |= 128;
spr.z -= tilesizy[WILLOW] << 8;
changespritestat(i, FACE);
}
END_WH_NS

View file

@ -0,0 +1,207 @@
#pragma once
#include "ns.h"
BEGIN_WH_NS
enum
{
MAXWEAPONS = 10,
MAXPOTIONS = 5,
BACKBUTTON = 9216,
BACKSCALE = 16384,
MOUSECURSOR = 9217,
RESERVED1 = 9218,
RESERVED2 = 9219,
WHLOGO = 9220,
MENUFONT = 9221, //+32
MINITEXTPOINT = 9254,
MINITEXTSLASH = 9255,
WH2FONTBIGLETTERS = 9256,
WH2FONTLILLETTERS = 9282,
WH2FONTNUMBERS = 9308,
WH2LOGO = 9335,
WH2FONTBACKGROUND = 9336,
ARROWCOUNTLIMIT = 100,
THROWPIKELIMIT = 100,
GRAVITYCONSTANT = (4 << 7) - 32,
JUMPVEL = (4 << 10) - 256,
WH2GRAVITYCONSTANT = (8 << 5),
WH2JUMPVEL = (6 << 10), //(8 << 10)
GROUNDBIT = 1,
PLATFORMBIT = 2,
TICSPERFRAME = 3,
TIMERRATE = 120,
kExtraTile = MAXTILES - MAXUSERTILES,
// Hit definitions
kHitTypeMask = 0xE000,
kHitIndexMask = 0x1FFF,
kHitFloor = 0x4000,
kHitSector = 0x4000,
kHitCeiling = 0x6000,
kHitWall = 0x8000,
kHitSprite = 0xC000,
PLAYERHEIGHT = 48,
WH2PLAYERHEIGHT = 64,
MAXNUMORBS = 8,
MAXHEALTH = 100,
MAXKEYS = 4,
MAXTREASURES = 18,
LOW = 1,
HIGH = 2,
TOP = 1,
BOTTOM = 2,
INACTIVE = 0,
PATROL = 1,
CHASE = 2,
AMBUSH = 3,
BIRTH = 4,
DODGE = 5,
ATTACK = 6,
DEATH = 7,
STAND = 8,
MISSILE = 100,
FX = 101,
HEATSEEKER = 102,
YELL = 103,
CAST = 104,
PUSH = 105,
FALL = 106,
DIE = 107,
DEAD = 108,
FACE = 109,
SHOVE = 110,
SHATTER = 111,
FIRE = 112,
LIFTUP = 113,
LIFTDN = 114,
PENDULUM = 115,
RESURECT = 116,
BOB = 117,
SHOVER = 118,
TORCHER = 119,
MASPLASH = 120,
CHUNKOMEAT = 121,
FLEE = 122,
DORMANT = 123,
ACTIVE = 124,
ATTACK2 = 125,
WITCHSIT = 126,
CHILL = 127,
SKIRMISH = 128,
FLOCK = 129,
FLOCKSPAWN = 130,
PAIN = 131,
WAR = 132,
TORCHLIGHT = 133,
GLOWLIGHT = 134,
BLOOD = 135,
DRIP = 136,
DEVILFIRE = 137,
FROZEN = 138,
PULLTHECHAIN = 139,
FLOCKCHIRP = 140,
CHUNKOWALL = 141,
FINDME = 142,
DRAIN = 143,
RATRACE = 144,
SMOKE = 145,
EXPLO = 146,
JAVLIN = 147,
ANIMLEVERUP = 148,
ANIMLEVERDN = 149,
BROKENVASE = 150,
NUKED = 151,
WARPFX = 152,
PATROLFLAG = 153,
PLACECONE = 154,
REMOVECONE = 155,
FIRSTCONE = 156,
GOTOCONE = 157,
TORCHFRONT = 158,
APATROLPOINT = 159,
SHADE = 160,
EVILSPIRIT = 161,
STONETOFLESH = 162,
SPARKS = 163,
SPARKSUP = 164,
SPARKSDN = 165,
LAND = 166,
SHARDOFGLASS = 167,
FIRECHUNK = 168,
DUDE = 170,
ACTIVATESECTOR = 1,
ACTIVATESECTORONCE = 2,
DOORUPTAG = 6,
DOORDOWNTAG = 7,
DOORSPLITHOR = 8,
DOORSPLITVER = 9,
DOORSWINGTAG = 13,
DOORBOX = 16,
PLATFORMELEVTAG = 1000,
BOXELEVTAG = 1003,
SECTOREFFECT = 104,
PULSELIGHT = 0,
FLICKERLIGHT = 1,
DELAYEFFECT = 2,
XPANNING = 3,
DOORDELAY = 480, // 4 second delay for doors to close
DOORSPEED = 128,
ELEVSPEED = 256,
PICKDISTANCE = 512, // for picking up sprites
PICKHEIGHT = 40,
PICKHEIGHT2 = 64,
JETPACKPIC = 93 , // sprites available to pick up
MAXSWINGDOORS = 32,
JETPACKITEM = 0,
SHOTGUNITEM = 1,
SHOTGUNPIC = 101,
SHOTGUNVIEW = 102,
KILLSECTOR = 4444,
TDIAMONDRING = 0, //armortype3 200units
TSHADOWAMULET = 1, //shadow
TGLASSSKULL = 2, //add score
TAHNK = 3, //health 250units
TBLUESCEPTER = 4, //lava walk
TYELLOWSCEPTER = 5, //water walk
TADAMANTINERING = 6, //unfinity attack protection
TONYXRING = 7, //projectiles protection
TPENTAGRAM = 8, //exit
TCRYSTALSTAFF = 9, //health 250units armortype2 200units
TAMULETOFTHEMIST = 10, //invisible
THORNEDSKULL = 11, //end game
TTHEHORN = 12, //vampire
TSAPHIRERING = 13, //set armortype to 3
TBRASSKEY = 14,
TBLACKKEY = 15,
TGLASSKEY = 16,
TIVORYKEY = 17,
};
END_WH_NS

View file

@ -0,0 +1,501 @@
#include "ns.h"
#include "gamecontrol.h"
short KNIFEREADY;
short KNIFEATTACK;
short RFIST;
short SWORDATTACK;
short MORNINGSTAR;
short BOWREADY;
short BOWREADYEND;
short BOWWALK;
short KNIFEATTACK2;
short SWORDPULL;
short SWORDATTACK2;
short MORNINGATTACK2;
short MUMEDUSA;
short MUTWOHANDS;
short BMUTWOHANDS;
short GOBSWORDPULL;
short GOBSWORDATTACK;
short GOBSWORDATTACK2;
short BIGAXEATTACK;
short BIGAXEATTACK2;
short BIGAXEDRAW;
short HALBERDATTACK1;
short HALBERDATTACK2;
short HALBERDDRAW;
short PIKEDRAW;
short PIKEATTACK1;
short EXCALATTACK1;
short EXCALATTACK2;
short EXCALDRAW;
short BIGAXEDRAW9;
short BIGAXEDRAW10;
short GEARS2START;
short HORNEDSKULL;
short THEFONT;
short CRYSTALSTAFF;
short TORCH;
short WEAPON1;
short WEAPON1A;
short AMULETOFTHEMIST;
short WEAPON2;
short BRASSKEY;
short BLACKKEY;
short GLASSKEY;
short IVORYKEY;
short NEWCHUNK;
short BOWLOFFIRE;
short SPAWNFIREBALL;
short PENTAGRAM;
short THEHORN;
short BOW;
short SWINGGATE3;
short PLATEARMOR;
short HELMET;
short CHAINMAIL;
short SCROLLSCARE;
short SCROLLNUKE;
short SCROLLFLY;
short SCROLLFIREBALL;
short SCROLLFREEZE;
short SCROLLNIGHT;
short SCROLLMAGIC;
short SCROLLOPEN;
short LEATHERARMOR;
short QUIVER;
short SWINGGATE4;
short SWINGGATE5;
short SMOKEFX;
short STANDINTORCH;
short PENTADOOR3;
short PENTADOOR4;
short PENTADOOR5;
short PENTADOOR6;
short PENTADOOR7;
short SCARY;
short FISH;
short LEVERUP;
short LEVERDOWN;
short SPAWNJAVLIN;
short RAT;
short GUARDIAN;
short GUARDIANATTACK;
short DART;
short WEAPON4;
short WEAPON6;
short WEAPON5;
short WEAPON5B;
short THROWHALBERD;
short WEAPON7;
short THROWPIKE;
short EXPLO2;
short SHATTERVASE;
short SHATTERVASE2;
short SHATTERVASE3;
short HANGMAN;
short SKELETON;
short SKELETONATTACK;
short SKELETONSKULL;
short SKELETONUP;
short SKELETONDIE;
short SKELETONDEAD;
short BONECHUNK1;
short BONECHUNKEND;
short PIKEATTACK2;
short GOBWEAPON;
short SFLASKBLUE;
short SFLASKGREEN;
short SFLASKOCHRE;
short SFLASKRED;
short SFLASKTAN;
short SFLASKBLACK;
short SHEALTHFONT;
short SSCOREFONT;
short SPOTIONFONT;
short SPOTIONBACKPIC;
short SPOTIONARROW;
short SSPELLBOOKBLANK;
short SSPELLBOOK2;
short SSPELLBOOK3;
short SSPELLBOOK4;
short SSPELLBOOK5;
short SSPELLBOOK6;
short SSPELLBOOK7;
short SSPELLBOOK8;
short SARROWS;
short SPLAYERLVL;
short SSTATUSBAR;
short SKEYBLANK;
short SKEYBRASS;
short SKEYBLACK;
short SKEYGLASS;
short SKEYIVORY;
short SHEALTHBACK;
short SSCOREBACKPIC;
short SNDEFFECT;
short SNDLOOP;
short SNDLOOPOFF;
short BROWNCHUNKSTART;
short GREYCHUNKSTART;
short REDCHUNKSTART;
short GREENCHUNKSTART;
short TANCHUNKSTART;
short WILLOW;
short SPIKES;
short STHEFLAG;
short GRONHALATTACK;
short GRONHALATTACKEND;
short GROLHALREADY;
short GRONHALREADYEND;
short GRONHAL;
short GRONHALPAIN;
short GRONHALDIE;
short GRONSWATTACK;
short GRONSW;
short GRONSWPAIN;
short GRONSWDIE;
short GRONMUATTACK;
short GRONDIE;
short GRONDEAD;
short GRONMU;
short GRONMUPAIN;
short GRONMUDIE;
short GRONSHIELD;
short SHIELD;
void InitNames()
{
if(!game.WH2) {
KNIFEREADY = 1249;
KNIFEATTACK = 1261;
RFIST = 1268;
SWORDATTACK = 1291;
MORNINGSTAR = 1306;
BOWREADY = 1313;
BOWREADYEND = 1319;
BOWWALK = 1323;
KNIFEATTACK2 = 1329;
SWORDPULL = 1333;
SWORDATTACK2 = 1340;
MORNINGATTACK2 = 1348;
MUMEDUSA = 1353;
MUTWOHANDS = 1363;
BMUTWOHANDS = 1378;
GOBSWORDPULL = 1390;
GOBSWORDATTACK = 1397;
GOBSWORDATTACK2 = 1404;
BIGAXEATTACK = 1411;
BIGAXEATTACK2 = 1421;
BIGAXEDRAW = 1429;
HALBERDATTACK1 = 1438;
HALBERDATTACK2 = 1443;
HALBERDDRAW = 1447;
PIKEDRAW = 1451;
PIKEATTACK1 = 1457;
EXCALATTACK1 = 1463;
EXCALATTACK2 = 1473;
EXCALDRAW = 1481;
BIGAXEDRAW9 = 1494;
BIGAXEDRAW10 = 1495;
GEARS2START = 1498;
HORNEDSKULL = 1503;
THEFONT = 1511;
CRYSTALSTAFF = 1551;
TORCH = 1554;
WEAPON1 = 1567;
WEAPON1A = 1571;
AMULETOFTHEMIST = 1575;
WEAPON2 = 1583;
BRASSKEY = 1624;
BLACKKEY = 1632;
GLASSKEY = 1640;
IVORYKEY = 1648;
NEWCHUNK = 1664;
BOWLOFFIRE = 1705;
SPAWNFIREBALL = 1718;
PENTAGRAM = 1760;
THEHORN = 1768;
BOW = 1776;
SWINGGATE3 = 1789;
PLATEARMOR = 1794;
HELMET = 1802;
CHAINMAIL = 1810;
SCROLLSCARE = 1818;
SCROLLNUKE = 1826;
SCROLLFLY = 1834;
SCROLLFIREBALL = 1842;
SCROLLFREEZE = 1850;
SCROLLNIGHT = 1858;
SCROLLMAGIC = 1866;
SCROLLOPEN = 1874;
LEATHERARMOR = 1882;
QUIVER = 1890;
SWINGGATE4 = 1898;
SWINGGATE5 = 1899;
SMOKEFX = 1904;
STANDINTORCH = 1908;
PENTADOOR3 = 1927;
PENTADOOR4 = 1928;
PENTADOOR5 = 1929;
PENTADOOR6 = 1930;
PENTADOOR7 = 1931;
SCARY = 1933;
FISH = 1945;
LEVERUP = 1947;
LEVERDOWN = 1949;
SPAWNJAVLIN = 1958;
RAT = 1962;
GUARDIAN = 1994;
GUARDIANATTACK = 2002;
DART = 2010;
WEAPON4 = 2027;
WEAPON6 = 2039;
WEAPON5 = 2047;
WEAPON5B = 2055;
THROWHALBERD = 2066;
WEAPON7 = 2067;
THROWPIKE = 2071;
EXPLO2 = 2096;
SHATTERVASE = 2124;
SHATTERVASE2 = 2131;
SHATTERVASE3 = 2138;
HANGMAN = 2145;
SKELETON = 2156;
SKELETONATTACK = 2181;
SKELETONSKULL = 2186;
SKELETONUP = 2191;
SKELETONDIE = 2192;
SKELETONDEAD = 2198;
BONECHUNK1 = 2199;
BONECHUNKEND = 2208;
PIKEATTACK2 = 2209;
GOBWEAPON = 2218;
SFLASKBLUE = 2240;
SFLASKGREEN = 2241;
SFLASKOCHRE = 2242;
SFLASKRED = 2243;
SFLASKTAN = 2244;
SFLASKBLACK = 2245;
SHEALTHFONT = 2246;
SSCOREFONT = 2256;
SPOTIONFONT = 2266;
SPOTIONBACKPIC = 2280;
SPOTIONARROW = 2281;
SSPELLBOOKBLANK = 2286;
SSPELLBOOK2 = 2294;
SSPELLBOOK3 = 2302;
SSPELLBOOK4 = 2310;
SSPELLBOOK5 = 2317;
SSPELLBOOK6 = 2324;
SSPELLBOOK7 = 2332;
SSPELLBOOK8 = 2340;
SARROWS = 2348;
SPLAYERLVL = 2349;
SSTATUSBAR = 2358;
SKEYBLANK = 2359;
SKEYBRASS = 2360;
SKEYBLACK = 2361;
SKEYGLASS = 2362;
SKEYIVORY = 2363;
SHEALTHBACK = 2365;
SSCOREBACKPIC = 2368;
SNDEFFECT = 2369;
SNDLOOP = 2370;
SNDLOOPOFF = 2371;
BROWNCHUNKSTART = 2387;
GREYCHUNKSTART = 2395;
REDCHUNKSTART = 2403;
GREENCHUNKSTART = 2411;
TANCHUNKSTART = 2419;
WILLOW = 2427;
SPIKES = 2488;
STHEFLAG = 2491;
GRONHALATTACK = 2504;
GRONHALATTACKEND = 2508;
GROLHALREADY = 2509;
GRONHALREADYEND = 2510;
GRONHAL = 2539;
GRONHALPAIN = 2559;
GRONHALDIE = 2560;
GRONSWATTACK = 2561;
GRONSW = 2581;
GRONSWPAIN = 2601;
GRONSWDIE = 2602;
GRONMUATTACK = 2603;
GRONDIE = 2633;
GRONDEAD = 2639;
GRONMU = 2640;
GRONMUPAIN = 2660;
GRONMUDIE = 2661;
GRONSHIELD = 2680;
SHIELD = 2684;
} else { //WH2
KNIFEREADY = 1248;
KNIFEATTACK = 1260;
RFIST = 1267;
SWORDATTACK = 1290;
MORNINGSTAR = 1305;
BOWREADY = 1312;
BOWREADYEND = 1318;
BOWWALK = 1322;
KNIFEATTACK2 = 1328;
SWORDPULL = 1332;
SWORDATTACK2 = 1339;
MORNINGATTACK2 = 1347;
MUMEDUSA = 1352;
MUTWOHANDS = 1362;
BMUTWOHANDS = 1377;
GOBSWORDPULL = 1389;
GOBSWORDATTACK = 1396;
GOBSWORDATTACK2 = 1403;
BIGAXEATTACK = 1410;
BIGAXEATTACK2 = 1420;
BIGAXEDRAW = 1428;
HALBERDATTACK1 = 1437;
HALBERDATTACK2 = 1442;
HALBERDDRAW = 1446;
PIKEDRAW = 1450;
PIKEATTACK1 = 1456;
EXCALATTACK1 = 1462;
EXCALATTACK2 = 1472;
EXCALDRAW = 1480;
BIGAXEDRAW9 = 1493;
BIGAXEDRAW10 = 1494;
GEARS2START = 1497;
HORNEDSKULL = 1502;
THEFONT = 1510;
CRYSTALSTAFF = 1550;
TORCH = 1553;
WEAPON1 = 1566;
WEAPON1A = 1570;
AMULETOFTHEMIST = 1574;
WEAPON2 = 1582;
BRASSKEY = 1623;
BLACKKEY = 1631;
GLASSKEY = 1639;
IVORYKEY = 1647;
NEWCHUNK = 1663;
BOWLOFFIRE = 1704;
SPAWNFIREBALL = 1717;
PENTAGRAM = 1759;
THEHORN = 1767;
BOW = 1775;
SWINGGATE3 = 1788;
PLATEARMOR = 1793;
HELMET = 1801;
CHAINMAIL = 1809;
SCROLLSCARE = 1817;
SCROLLNUKE = 1825;
SCROLLFLY = 1833;
SCROLLFIREBALL = 1841;
SCROLLFREEZE = 1849;
SCROLLNIGHT = 1857;
SCROLLMAGIC = 1865;
SCROLLOPEN = 1873;
LEATHERARMOR = 1881;
QUIVER = 1889;
SWINGGATE4 = 1897;
SWINGGATE5 = 1898;
SMOKEFX = 1903;
STANDINTORCH = 1907;
PENTADOOR3 = 1926;
PENTADOOR4 = 1927;
PENTADOOR5 = 1928;
PENTADOOR6 = 1929;
PENTADOOR7 = 1930;
SCARY = 1932;
FISH = 1944;
LEVERUP = 1946;
LEVERDOWN = 1948;
SPAWNJAVLIN = 1957;
RAT = 1961;
GUARDIAN = 1993;
GUARDIANATTACK = 2001;
DART = 2009;
WEAPON4 = 2026;
WEAPON6 = 2038;
WEAPON5 = 2046;
WEAPON5B = 2054;
THROWHALBERD = 2065;
WEAPON7 = 2066;
THROWPIKE = 2070;
EXPLO2 = 2095;
SHATTERVASE = 2123;
SHATTERVASE2 = 2130;
SHATTERVASE3 = 2137;
HANGMAN = 2144;
SKELETON = 2155;
SKELETONATTACK = 2180;
SKELETONSKULL = 2185;
SKELETONUP = 2190;
SKELETONDIE = 2191;
SKELETONDEAD = 2197;
BONECHUNK1 = 2198;
BONECHUNKEND = 2207;
PIKEATTACK2 = 2208;
GOBWEAPON = 2217;
SFLASKBLUE = 2239;
SFLASKGREEN = 2240;
SFLASKOCHRE = 2241;
SFLASKRED = 2242;
SFLASKTAN = 2243;
SFLASKBLACK = 2244;
SHEALTHFONT = 2245;
SSCOREFONT = 2255;
SPOTIONFONT = 2265;
SPOTIONBACKPIC = 2279;
SPOTIONARROW = 2280;
SSPELLBOOKBLANK = 2285;
SSPELLBOOK2 = 2293;
SSPELLBOOK3 = 2301;
SSPELLBOOK4 = 2309;
SSPELLBOOK5 = 2316;
SSPELLBOOK6 = 2323;
SSPELLBOOK7 = 2331;
SSPELLBOOK8 = 2339;
SARROWS = 2347;
SPLAYERLVL = 2348;
SSTATUSBAR = 2357;
SKEYBLANK = 2358;
SKEYBRASS = 2359;
SKEYBLACK = 2360;
SKEYGLASS = 2361;
SKEYIVORY = 2362;
SHEALTHBACK = 2364;
SSCOREBACKPIC = 2367;
SNDEFFECT = 2368;
SNDLOOP = 2369;
SNDLOOPOFF = 2370;
BROWNCHUNKSTART = 2386;
GREYCHUNKSTART = 2394;
REDCHUNKSTART = 2402;
GREENCHUNKSTART = 2410;
TANCHUNKSTART = 2418;
WILLOW = 2426;
SPIKES = 2487;
STHEFLAG = 2490;
GRONHALATTACK = 2502;
GRONHALATTACKEND = 2506;
GROLHALREADY = 2507;
GRONHALREADYEND = 2508;
GRONHAL = 2537;
GRONHALPAIN = 2557;
GRONHALDIE = 2558;
GRONSWATTACK = 2559;
GRONSW = 2579;
GRONSWPAIN = 2599;
GRONSWDIE = 2600;
GRONMUATTACK = 2601;
GRONDIE = 2631;
GRONDEAD = 2637;
GRONMU = 2638;
GRONMUPAIN = 2658;
GRONMUDIE = 2659;
GRONSHIELD = 2678;
SHIELD = 2682;
}
}
END_WH_NS

View file

@ -0,0 +1,388 @@
BEGIN_WH_NS
enum Names {
TILES000_START = 0,
SLIME = 5,
DRYWATER = 22,
DRYSLIME = 33,
COOLLAVA = 58,
ANILAVA = 61,
LAVA1 = 62,
WOODPLANK = 68,
SKY = 75,
LAVA = 79,
LAVA2 = 80,
HEALTHWATER = 86,
WATER = 90,
COOLLAVA2 = 103,
SPLASHAROO = 160,
LASTSPLASHAROO = 166,
SKY2 = 167,
SKY3 = 168,
SKY4 = 169,
SKY5 = 170,
SKY6 = 171,
SKY7 = 172,
TILES001_START = 247,
GIFTBOX = 260,
OPENCHEST = 263,
BARREL = 269,
SPACEPLANK = 271,
PENTADOOR1 = 280,
PENTADOOR2 = 281,
ROPEDOOR = 282,
TELEPAD = 291,
BULLET = 294,
PINE = 308,
SWINGDOOR = 324,
SWINGDOOR2 = 325,
SWINGDOOR3 = 326,
BAT = 330,
FBARREL = 340,
FBARRELFALL = 341,
FSHATTERBARREL = 342,
BOULDER = 361,
PULLCHAIN1 = 370,
PULLCHAIN2 = 371,
PULLCHAIN3 = 372,
SAPHIRERING = 373,
TALLSWING = 385,
TALLSWING2 = 386,
SPARKFX = 390,
VASEA = 392,
VASEB = 393,
VASEC = 394,
HEALTHPOTION = 401,
FIREWALKPOTION = 402,
STRENGTHPOTION = 403,
INVISIBLEPOTION = 404,
ARMORPOTION = 406,
LAVASPLASH = 423,
LASTLAVASPLASH = 437,
SPIKEBLADE = 461,
SPIKE = 462,
SPIKEPOLE = 463,
HORIZSPIKEPOLE = 464,
HORIZSPIKE = 465,
HORIZSPIKEBLADE = 466,
GEARSSTART = 467,
GEARSEND = 474,
SWINGHOLE = 476,
SWINGGATE = 477,
SWINGGATE2 = 478,
WOODGEARSSTART = 483,
WOODGEARSEND = 486,
SQUAREGRATE = 490,
MAINMENU = 500,
TITLEPIC = 501,
SAVEPIC = 502,
SAVENUMBERS = 503,
LOADPIC = 504,
AREYOUSURE = 505,
BLOODGORERED = 506,
DIFFICULTRED = 507,
BLOODGOREGREEN = 508,
DIFFICULTGREEN = 509,
HORNYSKULL1 = 510,
HORNYSKULL2 = 511,
HORNYSKULL3 = 512,
HORNYSKULL4 = 513,
HORNYBACK = 514,
LOADRED = 515,
SAVERED = 516,
LOADGREEN = 517,
SAVEGREEN = 518,
MENUSELECTIONS = 519,
NEWGAMEGREEN = 520,
LOADSAVEGREEN = 521,
BLOODGOREGREEN2 = 522,
HELPGREEN = 523,
QUITGREEN = 524,
NOGORESHADOW = 525,
NOGORESOLID = 526,
GORESHADOW = 527,
GORESOLID = 528,
VDARK = 529,
MDARK = 530,
FLICKER = 531,
XDARK = 532,
BACKGROUND = 536,
WALLARROW = 537,
MUHANDS = 538,
STATUSBAR = 545,
ORB1 = 546,
ORB2 = 547,
FLASKBLUE = 548,
FLASKGREEN = 549,
FLASKOCHRE = 550,
FLASKRED = 551,
FLASKTAN = 552,
FLASKBLACK = 553,
BGZERO = 554,
BGONE = 555,
BGTWO = 556,
BGTHREE = 557,
BGFOUR = 558,
BGFIVE = 559,
BGSIX = 560,
BGSEVEN = 561,
BGEIGHT = 562,
BGNINE = 563,
SCOREFONT = 564,
MDONE = 565,
MDTWO = 566,
MDTHREE = 567,
MDFOUR = 568,
MDFIVE = 569,
MDSIX = 570,
MDSEVEN = 571,
MDEIGHT = 572,
MDNINE = 573,
SMFONT = 574,
SMONE = 575,
SMTWO = 576,
SMTHREE = 577,
SMFOUR = 578,
SMFIVE = 579,
SMSIX = 580,
SMSEVEN = 581,
SMEIGHT = 582,
SMNINE = 583,
SCOREBACKPIC = 584,
WEAPONBACKPIC = 585,
HEALTHBACKPIC = 586,
BOOKBACKPIC = 587,
ORBBACKPIC = 588,
POTIONBACKPIC = 589,
POTIONARROW = 590,
ORB3 = 595,
ORB4 = 596,
ORB5 = 597,
ORB6 = 598,
ORB7 = 599,
ORB8 = 600,
WAVES1_SND = 607,
WAVES2_SND = 608,
WIND1_SND = 609,
WIND2_SND = 610,
LAVA1_SND = 611,
LAVA2_SND = 612,
DIESPIKE = 613,
SPELLBOOKBLANK = 618,
SPELLBOOK2 = 627,
SPELLBOOK3 = 636,
CHUNK1 = 645,
CHUNK2 = 646,
CHUNK3 = 647,
CHUNK4 = 648,
PLASMA = 649,
ANNIHILATE = 650,
WILLOWEXPLO = 653,
EXPLOSION = 656,
FATSPANK = 658,
MONSTERBALL = 660,
ICECUBE = 663,
DISTORTIONBLAST = 664,
SPELLBOOKBACK = 665,
WEAPON3 = 666,
ORB = 674,
SPAWN = 675,
ARMOR = 676,
POTION = 677,
WEAPON = 678,
COPYRIGHT = 679,
DIAMONDRING = 694,
SHADOWAMULET = 698,
GLASSSKULL = 706,
AHNK = 714,
BLUESCEPTER = 718,
YELLOWSCEPTER = 722,
ADAMANTINERING = 726,
ONYXRING = 730,
TILES003_START = 736,
KOBOLD = 737,
KOBOLDATTACK = 762,
KOBOLDDIE = 765,
KOBOLDDEAD = 770,
KOBOLDTORCH = 771,
DEVILSTAND = 772,
DEVIL = 777,
DEVILATTACK = 797,
DEVILPAIN = 809,
DEVILDIE = 814,
DEVILDEAD = 820,
TILES004_START = 980,
MINOTAUR = 981,
MINOTAURATTACK = 1001,
MINOTAURPAIN = 1012,
MINOTAURDIE = 1017,
MINOTAURDEAD = 1027,
};
extern short KNIFEREADY;
extern short KNIFEATTACK;
extern short RFIST;
extern short SWORDATTACK;
extern short MORNINGSTAR;
extern short BOWREADY;
extern short BOWREADYEND;
extern short BOWWALK;
extern short KNIFEATTACK2;
extern short SWORDPULL;
extern short SWORDATTACK2;
extern short MORNINGATTACK2;
extern short MUMEDUSA;
extern short MUTWOHANDS;
extern short BMUTWOHANDS;
extern short GOBSWORDPULL;
extern short GOBSWORDATTACK;
extern short GOBSWORDATTACK2;
extern short BIGAXEATTACK;
extern short BIGAXEATTACK2;
extern short BIGAXEDRAW;
extern short HALBERDATTACK1;
extern short HALBERDATTACK2;
extern short HALBERDDRAW;
extern short PIKEDRAW;
extern short PIKEATTACK1;
extern short EXCALATTACK1;
extern short EXCALATTACK2;
extern short EXCALDRAW;
extern short BIGAXEDRAW9;
extern short BIGAXEDRAW10;
extern short GEARS2START;
extern short HORNEDSKULL;
extern short THEFONT;
extern short CRYSTALSTAFF;
extern short TORCH;
extern short WEAPON1;
extern short WEAPON1A;
extern short AMULETOFTHEMIST;
extern short WEAPON2;
extern short BRASSKEY;
extern short BLACKKEY;
extern short GLASSKEY;
extern short IVORYKEY;
extern short NEWCHUNK;
extern short BOWLOFFIRE;
extern short SPAWNFIREBALL;
extern short PENTAGRAM;
extern short THEHORN;
extern short BOW;
extern short SWINGGATE3;
extern short PLATEARMOR;
extern short HELMET;
extern short CHAINMAIL;
extern short SCROLLSCARE;
extern short SCROLLNUKE;
extern short SCROLLFLY;
extern short SCROLLFIREBALL;
extern short SCROLLFREEZE;
extern short SCROLLNIGHT;
extern short SCROLLMAGIC;
extern short SCROLLOPEN;
extern short LEATHERARMOR;
extern short QUIVER;
extern short SWINGGATE4;
extern short SWINGGATE5;
extern short SMOKEFX;
extern short STANDINTORCH;
extern short PENTADOOR3;
extern short PENTADOOR4;
extern short PENTADOOR5;
extern short PENTADOOR6;
extern short PENTADOOR7;
extern short SCARY;
extern short FISH;
extern short LEVERUP;
extern short LEVERDOWN;
extern short SPAWNJAVLIN;
extern short RAT;
extern short GUARDIAN;
extern short GUARDIANATTACK;
extern short DART;
extern short WEAPON4;
extern short WEAPON6;
extern short WEAPON5;
extern short WEAPON5B;
extern short THROWHALBERD;
extern short WEAPON7;
extern short THROWPIKE;
extern short EXPLO2;
extern short SHATTERVASE;
extern short SHATTERVASE2;
extern short SHATTERVASE3;
extern short HANGMAN;
extern short SKELETON;
extern short SKELETONATTACK;
extern short SKELETONSKULL;
extern short SKELETONUP;
extern short SKELETONDIE;
extern short SKELETONDEAD;
extern short BONECHUNK1;
extern short BONECHUNKEND;
extern short PIKEATTACK2;
extern short GOBWEAPON;
extern short SFLASKBLUE;
extern short SFLASKGREEN;
extern short SFLASKOCHRE;
extern short SFLASKRED;
extern short SFLASKTAN;
extern short SFLASKBLACK;
extern short SHEALTHFONT;
extern short SSCOREFONT;
extern short SPOTIONFONT;
extern short SPOTIONBACKPIC;
extern short SPOTIONARROW;
extern short SSPELLBOOKBLANK;
extern short SSPELLBOOK2;
extern short SSPELLBOOK3;
extern short SSPELLBOOK4;
extern short SSPELLBOOK5;
extern short SSPELLBOOK6;
extern short SSPELLBOOK7;
extern short SSPELLBOOK8;
extern short SARROWS;
extern short SPLAYERLVL;
extern short SSTATUSBAR;
extern short SKEYBLANK;
extern short SKEYBRASS;
extern short SKEYBLACK;
extern short SKEYGLASS;
extern short SKEYIVORY;
extern short SHEALTHBACK;
extern short SSCOREBACKPIC;
extern short SNDEFFECT;
extern short SNDLOOP;
extern short SNDLOOPOFF;
extern short BROWNCHUNKSTART;
extern short GREYCHUNKSTART;
extern short REDCHUNKSTART;
extern short GREENCHUNKSTART;
extern short TANCHUNKSTART;
extern short WILLOW;
extern short SPIKES;
extern short STHEFLAG;
extern short GRONHALATTACK;
extern short GRONHALATTACKEND;
extern short GROLHALREADY;
extern short GRONHALREADYEND;
extern short GRONHAL;
extern short GRONHALPAIN;
extern short GRONHALDIE;
extern short GRONSWATTACK;
extern short GRONSW;
extern short GRONSWPAIN;
extern short GRONSWDIE;
extern short GRONMUATTACK;
extern short GRONDIE;
extern short GRONDEAD;
extern short GRONMU;
extern short GRONMUPAIN;
extern short GRONMUDIE;
extern short GRONSHIELD;
extern short SHIELD;
END_WH_NS

View file

@ -0,0 +1,90 @@
#pragma once
BEGIN_WH_NS
struct PLAYER {
//Input pInput;
int x,y,z;
float ang;
float horiz, jumphoriz;
int height;
int hvel;
short sector;
short oldsector;
short spritenum;
boolean keytoggle;
int flags;
int weapon[MAXWEAPONS], preenchantedweapon[MAXWEAPONS];
int ammo[MAXWEAPONS], preenchantedammo[MAXWEAPONS];
int orbammo[MAXNUMORBS];
int treasure[MAXTREASURES];
int orbactive[MAXNUMORBS];
int orb[MAXNUMORBS];
int potion[MAXPOTIONS];
int lvl;
int score;
int health;
int maxhealth;
int armor;
int armortype;
int onsomething;
int fallz;
boolean dead;
short turnAround;
int shadowtime;
int helmettime;
int scoretime;
int vampiretime;
int selectedgun;
int currweapon;
int currweapontics;
int currweaponanim;
int currweaponframe;
int currweaponfired;
int currweaponattackstyle;
int currweaponflip;
int hasshot;
int currentpotion;
int strongtime, manatime, invisibletime=-1;
int orbshot;
int spellbooktics;
int spellbook;
int spellbookframe;
int spellbookflip;
int nightglowtime;
int showbook;
int showbooktype;
int showbookflip;
int showbookanim;
int currentorb;
int spelltime;
int shieldpoints;
int shieldtype;
int poisoned;
int poisontime;
int shockme = -1;
int invincibletime;
int spiked;
int spiketics;
int spikeframe;
int currspikeframe;
boolean godMode;
boolean noclip;
// no copy assignments for this one!
PLAYER(const PLAYER&) = delete;
PLAYER& operator=(const PLAYER&) = delete;
};
END_WH_NS

View file

@ -0,0 +1,17 @@
#pragma once
#include "build.h"
BEGIN_WH_NS
using SPRITE = spritetype;
using boolean = bool;
END_WH_NS
#include "globals.h"
#include "names.h"
#include "wh1names.h"
#include "wh2names.h"
#include "player.h"
#include "ai.h"

View file

@ -0,0 +1,266 @@
#pragma once
BEGIN_WH_NS
enum WH1Names {
SKY8 = 179,
SKY9 = 180,
SKY10 = 181,
FIREBALL = 314,
LFIRE = 345,
SFIRE = 353,
WATERSPLASH = 438,
LASTWATERSPLASH = 446,
GLOW = 451,
COMPASS = 499,
MACEWITHSPIKES = 540,
MACE = 541,
KNIFE = 542,
SWORD1 = 543,
SWORD2 = 544,
GYSER = 680,
FATWITCH = 821,
FATWITCHATTACK = 841,
FATWITCHDIE = 846,
FATWITCHDEAD = 852,
SWAPCHILL = 853,
SWAMPSTAND = 859,
SWAMPTHING = 860,
SWAMPATTACK = 862,
FREDSTAND = 866,
FRED = 871,
FREDATTACK = 891,
FREDPAIN = 906,
FREDDIE = 911,
FREDDEAD = 916,
GOBLINSTAND = 917,
GOBLIN = 922,
GOBLINCHILL = 942,
GOBLINSURPRISE = 946,
GOBLINATTACK = 952,
GOBLINPAIN = 963,
GOBLINDIE = 968,
GOBLINDEAD = 977,
SKULLY = 1028,
SKULLYATTACK = 1048,
SKULLYDIE = 1059,
SKULLYDEAD = 1069,
SPIDER = 1070,
SPIDERDIE = 1110,
SPIDERDEAD = 1117,
JUDYSIT = 1118,
JUDYSTAND = 1119,
JUDY = 1123,
JUDYATTACK1 = 1143,
JUDYATTACK2 = 1150,
JUDYDIE = 1159,
JUDYDEAD = 1163,
DRAGONATTACK = 1164,
DRAGONDIE = 1187,
DRAGONDEAD = 1200,
DRAGON = 1201,
DRAGONATTACK2 = 1207,
DOG = 1213,
TILES005_START = 1221,
SVGAMENU2 = 1990,
SVGAMENU = 1991,
GASCLOUD = 2021,
POISONICON = 2373,
SKULLYCHAR = 2433,
DEVILCHAR = 2438,
DRAGONCHAR = 2443,
FATWITCHCHAR = 2448,
GOBLINCHAR = 2453,
JUDYCHAR = 2458,
KOBOLDCHAR = 2463,
MINOTAURCHAR = 2468,
SKELETONCHAR = 2473,
GRONCHAR = 2483,
GUARDIANCHAR = 2498,
BETAPAGE = 2691,
STONEHENGE = 2698,
SVGAVICTORYA1 = 2699,
SVGAVICTORYA2 = 2700,
VICTORYA = 2703,
VICTORYB = 2704,
SVGAVICTORYB1 = 2705,
SVGAVICTORYB2 = 2706,
SVB1 = 2707,
SVB2 = 2708,
SVBR1 = 2709,
SVBR2 = 2710,
VICTORYC = 2714,
SVP1 = 2715,
SVP2 = 2716,
SVR1 = 2717,
SVR2 = 2718,
WH1KNIFEREADY = 1249,
WH1KNIFEATTACK = 1261,
WH1RFIST = 1268,
WH1SWORDATTACK = 1291,
WH1MORNINGSTAR = 1306,
WH1BOWREADY = 1313,
WH1BOWREADYEND = 1319,
WH1BOWWALK = 1323,
WH1KNIFEATTACK2 = 1329,
WH1SWORDPULL = 1333,
WH1SWORDATTACK2 = 1340,
WH1MORNINGATTACK2 = 1348,
WH1MUMEDUSA = 1353,
WH1MUTWOHANDS = 1363,
WH1BMUTWOHANDS = 1378,
WH1GOBSWORDPULL = 1390,
WH1GOBSWORDATTACK = 1397,
WH1GOBSWORDATTACK2 = 1404,
WH1BIGAXEATTACK = 1411,
WH1BIGAXEATTACK2 = 1421,
WH1BIGAXEDRAW = 1429,
WH1HALBERDATTACK1 = 1438,
WH1HALBERDATTACK2 = 1443,
WH1HALBERDDRAW = 1447,
WH1PIKEDRAW = 1451,
WH1PIKEATTACK1 = 1457,
WH1EXCALATTACK1 = 1463,
WH1EXCALATTACK2 = 1473,
WH1EXCALDRAW = 1481,
WH1BIGAXEDRAW9 = 1494,
WH1BIGAXEDRAW10 = 1495,
WH1GEARS2START = 1498,
WH1HORNEDSKULL = 1503,
WH1THEFONT = 1511,
WH1CRYSTALSTAFF = 1551,
WH1TORCH = 1554,
WH1WEAPON1 = 1567,
WH1WEAPON1A = 1571,
WH1AMULETOFTHEMIST = 1575,
WH1WEAPON2 = 1583,
WH1BRASSKEY = 1624,
WH1BLACKKEY = 1632,
WH1GLASSKEY = 1640,
WH1IVORYKEY = 1648,
WH1NEWCHUNK = 1664,
WH1BOWLOFFIRE = 1705,
WH1SPAWNFIREBALL = 1718,
WH1PENTAGRAM = 1760,
WH1THEHORN = 1768,
WH1BOW = 1776,
WH1SWINGGATE3 = 1789,
WH1PLATEARMOR = 1794,
WH1HELMET = 1802,
WH1CHAINMAIL = 1810,
WH1SCROLLSCARE = 1818,
WH1SCROLLNUKE = 1826,
WH1SCROLLFLY = 1834,
WH1SCROLLFIREBALL = 1842,
WH1SCROLLFREEZE = 1850,
WH1SCROLLNIGHT = 1858,
WH1SCROLLMAGIC = 1866,
WH1SCROLLOPEN = 1874,
WH1LEATHERARMOR = 1882,
WH1QUIVER = 1890,
WH1SWINGGATE4 = 1898,
WH1SWINGGATE5 = 1899,
WH1SMOKEFX = 1904,
WH1STANDINTORCH = 1908,
WH1PENTADOOR3 = 1927,
WH1PENTADOOR4 = 1928,
WH1PENTADOOR5 = 1929,
WH1PENTADOOR6 = 1930,
WH1PENTADOOR7 = 1931,
WH1SCARY = 1933,
WH1FISH = 1945,
WH1LEVERUP = 1947,
WH1LEVERDOWN = 1949,
WH1SPAWNJAVLIN = 1958,
WH1RAT = 1962,
WH1GUARDIAN = 1994,
WH1GUARDIANATTACK = 2002,
WH1DART = 2010,
WH1WEAPON4 = 2027,
WH1WEAPON6 = 2039,
WH1WEAPON5 = 2047,
WH1WEAPON5B = 2055,
WH1THROWHALBERD = 2066,
WH1WEAPON7 = 2067,
WH1THROWPIKE = 2071,
WH1EXPLO2 = 2096,
WH1SHATTERVASE = 2124,
WH1SHATTERVASE2 = 2131,
WH1SHATTERVASE3 = 2138,
WH1HANGMAN = 2145,
WH1SKELETON = 2156,
WH1SKELETONATTACK = 2181,
WH1SKELETONSKULL = 2186,
WH1SKELETONUP = 2191,
WH1SKELETONDIE = 2192,
WH1SKELETONDEAD = 2198,
WH1BONECHUNK1 = 2199,
WH1BONECHUNKEND = 2208,
WH1PIKEATTACK2 = 2209,
WH1GOBWEAPON = 2218,
WH1SFLASKBLUE = 2240,
WH1SFLASKGREEN = 2241,
WH1SFLASKOCHRE = 2242,
WH1SFLASKRED = 2243,
WH1SFLASKTAN = 2244,
WH1SFLASKBLACK = 2245,
WH1SHEALTHFONT = 2246,
WH1SSCOREFONT = 2256,
WH1SPOTIONFONT = 2266,
WH1SPOTIONBACKPIC = 2280,
WH1SPOTIONARROW = 2281,
WH1SSPELLBOOKBLANK = 2286,
WH1SSPELLBOOK2 = 2294,
WH1SSPELLBOOK3 = 2302,
WH1SSPELLBOOK4 = 2310,
WH1SSPELLBOOK5 = 2317,
WH1SSPELLBOOK6 = 2324,
WH1SSPELLBOOK7 = 2332,
WH1SSPELLBOOK8 = 2340,
WH1SARROWS = 2348,
WH1SPLAYERLVL = 2349,
WH1SSTATUSBAR = 2358,
WH1SKEYBLANK = 2359,
WH1SKEYBRASS = 2360,
WH1SKEYBLACK = 2361,
WH1SKEYGLASS = 2362,
WH1SKEYIVORY = 2363,
WH1SHEALTHBACK = 2365,
WH1SSCOREBACKPIC = 2368,
WH1SNDEFFECT = 2369,
WH1SNDLOOP = 2370,
WH1SNDLOOPOFF = 2371,
WH1BROWNCHUNKSTART = 2387,
WH1GREYCHUNKSTART = 2395,
WH1REDCHUNKSTART = 2403,
WH1GREENCHUNKSTART = 2411,
WH1TANCHUNKSTART = 2419,
WH1WILLOW = 2427,
WH1SPIKES = 2488,
WH1STHEFLAG = 2491,
WH1GRONHALATTACK = 2504,
WH1GRONHALATTACKEND = 2508,
WH1GROLHALREADY = 2509,
WH1GRONHALREADYEND = 2510,
WH1GRONHAL = 2539,
WH1GRONHALPAIN = 2559,
WH1GRONHALDIE = 2560,
WH1GRONSWATTACK = 2561,
WH1GRONSW = 2581,
WH1GRONSWPAIN = 2601,
WH1GRONSWDIE = 2602,
WH1GRONMUATTACK = 2603,
WH1GRONDIE = 2633,
WH1GRONDEAD = 2639,
WH1GRONMU = 2640,
WH1GRONMUPAIN = 2660,
WH1GRONMUDIE = 2661,
WH1GRONSHIELD = 2680,
WH1SHIELD = 2684,
};
END_WH_NS

View file

@ -0,0 +1,389 @@
#include "ns.h"
BEGIN_WH_NS
enum WH2Names {
STAINQ = 180,
FLOORMIRROR = 182,
STARMAP = 208,
BLOODSPLAT1 = 212,
BLOODSPLAT1END = 222,
BLOODSPLAT2 = 223,
BLOODSPLAT2END = 228,
WEAPON8 = 229,
SILVERBAG = 234,
GOLDBAG = 235,
GOLDBAG2 = 236,
GOLDCOINS = 237,
GOLDCOINS2 = 238,
SILVERCOINS = 239,
WALLPIKE = 356,
WALLSWORD = 357,
WALLBOW = 358,
WALLAXE = 359,
STAINTRIANGLE = 410,
STAINFLOWER = 411,
STAINTHIN = 412,
PATROLPOINT = 447,
CONE = 449,
STAINCIRCLE = 451,
STAINCIRCLEBREAK = 452,
STAINCIRCLEEND = 457,
STAINHEAD = 498,
STAINSNAKE = 499,
SKULLPULLCHAIN1 = 539,
GONZOSHIELD = 540,
SKULLPULLCHAIN3 = 541,
SPARKBALL = 602,
WEAPON3A = 670,
SLIMESPLASH = 821,
LASTSLIMESPLASH = 827,
DAFONT = 864,
ZFIRE = 905,
IMP = 922,
IMPATTACK = 952,
IMPDIE = 958,
IMPPAIN = 959,
IMPDEAD = 967,
THEMAINMENU = 1028,
THEMAINMENUWITH = 1029,
THENEWGAME = 1030,
THELOADSAVE = 1031,
THEOPTIONS = 1032,
THEHELP = 1033,
THEQUIT = 1034,
ZCREDITS = 1035,
ZWEAPON = 1036,
ZSPELL = 1037,
ZKEN = 1038,
ZCREDITS2 = 1039,
ZMOVE = 1040,
ZMOVE2 = 1041,
ZPOTION = 1042,
ZCREDITS3 = 1043,
ZARTIST = 1044,
ZSAVE = 1045,
ZLOAD = 1046,
ZGOREPG = 1047,
VMAINBLANK = 1048,
VMAIN = 1049,
VNEW = 1050,
VCREDIT1 = 1055,
DALOAD = 1065,
DASAVE = 1066,
ZLOADSAVE = 1067,
ZSURE = 1068,
THEORDER = 1069,
STHEORDER = 1070,
ZOPS = 1072,
DASOUND = 1073,
DAGAMEPLAY = 1074,
DACONTROLS = 1075,
DASLIDER = 1076,
ZCDPLAYER = 1077,
STAINGLASS1 = 1079,
STAINGLASS2 = 1086,
STAINGLASS3 = 1093,
STAINGLASS4 = 1100,
STAINGLASS5 = 1107,
STAINGLASS6 = 1114,
STAINGLASS7 = 1121,
STAINGLASS8 = 1128,
STAINGLASS9 = 1135,
CDMUVOL = 1142,
REDSHUFFLE = 1164,
ZZGORE = 1182,
ZZBLOOD = 1183,
ZZDIFFICULTY = 1184,
ZCONTROLS = 1185,
ZZSLIDER = 1198,
ZZON = 1199,
ZZOFF = 1200,
ZZONLITE = 1201,
ZZOFFLITE = 1202,
EXPLOSTART = 1203,
EXPLOEND = 1215,
ARROWFLAME = 1216,
STAINSCENE = 1658,
STAINSKULL = 1660,
STAINGARGO = 1661,
STAINMU = 1662,
SHARD = 1687,
DEMON = 1935,
GONZOBSHIELD = 2432,
GONZOCSHIELD = 2439,
GONZOGSHIELD = 2446,
STONEGONZOCHM = 2483,
STONEGONZOGSH = 2484,
STONEGRONDOVAL = 2485,
STONEGONZOBSW = 2486,
STONEGONZOBSH = 2497,
STONEGONZOBSW2 = 2498,
SBLUEKNIGHTS1 = 2705,
SBLUEKNIGHTS2 = 2706,
SBROWNKNIGHTS1 = 2707,
SBROWNKNIGHTS2 = 2708,
SPURPLEKNIGHTS1 = 2713,
SPURPLEKNIGHTS2 = 2714,
SREDKNIGHTS1 = 2715,
SREDKNIGHTS2 = 2716,
NEWGUYBOW = 2750,
NEWGUYPUNCH = 2780,
GONZOBSHPAIN = 3006,
GONZOBSHDEAD = 3016,
GONZOCSW = 3017,
GONZOCSWAT = 3047,
GONZOCSWPAIN = 3077,
GONZOCSWDEAD = 3089,
KURTSTAND = 3090,
KURTKNEE = 3095,
KURTJUMP = 3100,
KURTAT = 3110,
GONZOCHMAT = 3120,
KURTPUNCH = 3140,
KURTREADY = 3160,
NEWGUY = 3170,
NEWGUYMACE = 3200,
NEWGUYDIE = 3230,
NEWGUYDEAD = 3239,
NEWGUYSTAND = 3243,
NEWGUYKNEE = 3248,
GONZOCSHPAIN = 3268,
GONZOCSHDEAD = 3278,
GONZOGSW = 3279,
GONZOGSWAT = 3309,
GONZOGSWPAIN = 3339,
GONZOGSWDEAD = 3351,
GONZOGHM = 3352,
GONZOGHMAT = 3382,
GONZOGHMPAIN = 3412,
GONZOGHMDEAD = 3425,
GONZOGSH = 3426,
GONZOGSHAT = 3474,
GONZOGSHPAIN = 3530,
GONZOGSHDEAD = 3540,
KATIE = 3541,
KATIEASS = 3561,
KATIEAT = 3566,
KATIEPAIN = 3583,
KATIEDEAD = 3591,
NEWGUYMACEMU = 3592,
NEWGUYCAST = 3602,
NEWGUYPAIN = 3612,
GONZOHMJUMP = 3630,
GONZOHMJUMPEND = 3635,
GONZOSHJUMP = 3636,
GONZOSHJUMPEND = 3641,
ZFLASHER1 = 3650,
ZFLASHER2 = 3662,
SFLASH1 = 3680,
SFLASH2 = 3692,
SFLASH4 = 3704,
SFLASH3 = 3707,
VLOAD = 3711,
VSAVE = 3712,
VSOUNDA = 3713,
VSOUNDB = 3714,
VGOREA = 3715,
VGOREB = 3716,
ZPIKEREADY = 3743,
ZPIKE = 3748,
ZPIKEATTACK = 3752,
ZPIKEATTACK2 = 3758,
ZBOWREADY = 3767,
ZBOWREADYEND = 3774,
ZBOWCOCK = 3775,
ZBOWWALK = 3776,
ZBOWATTACK = 3781,
ZKNIFEREADY = 3786,
ZKNIFEATTACK = 3798,
ZKNIFEATTACK2 = 3804,
ZAXEREADY = 3808,
ZAXEATTACK = 3817,
ZAXEATTACK2 = 3832,
ZFREEZE = 3840,
ZFIREBALL = 3855,
ZLIGHT = 3865,
ZSTARATTACK = 3875,
ZSTARATTACK2 = 3884,
ZTWOHANDREADY = 3888,
ZTWOHANDATTACK = 3900,
ZTWOHANDATTACK2 = 3915,
ZSHORTREADY = 3922,
ZSHORTATTACK = 3929,
ZSHORTATTACKONE = 3933,
ZSHORTATTACK2 = 3939,
ZHALBERDREADY = 3946,
ZHALBERDATTACK = 3948,
ZHALBERDATTACK2 = 3957,
ROUNDSHIELD = 3961,
WH2KNIFEREADY = 1248,
WH2KNIFEATTACK = 1260,
WH2RFIST = 1267,
WH2SWORDATTACK = 1290,
WH2MORNINGSTAR = 1305,
WH2BOWREADY = 1312,
WH2BOWREADYEND = 1318,
WH2BOWWALK = 1322,
WH2KNIFEATTACK2 = 1328,
WH2SWORDPULL = 1332,
WH2SWORDATTACK2 = 1339,
WH2MORNINGATTACK2 = 1347,
WH2MUMEDUSA = 1352,
WH2MUTWOHANDS = 1362,
WH2BMUTWOHANDS = 1377,
WH2GOBSWORDPULL = 1389,
WH2GOBSWORDATTACK = 1396,
WH2GOBSWORDATTACK2 = 1403,
WH2BIGAXEATTACK = 1410,
WH2BIGAXEATTACK2 = 1420,
WH2BIGAXEDRAW = 1428,
WH2HALBERDATTACK1 = 1437,
WH2HALBERDATTACK2 = 1442,
WH2HALBERDDRAW = 1446,
WH2PIKEDRAW = 1450,
WH2PIKEATTACK1 = 1456,
WH2EXCALATTACK1 = 1462,
WH2EXCALATTACK2 = 1472,
WH2EXCALDRAW = 1480,
WH2BIGAXEDRAW9 = 1493,
WH2BIGAXEDRAW10 = 1494,
WH2GEARS2START = 1497,
WH2HORNEDSKULL = 1502,
WH2THEFONT = 1510,
WH2CRYSTALSTAFF = 1550,
WH2TORCH = 1553,
WH2WEAPON1 = 1566,
WH2WEAPON1A = 1570,
WH2AMULETOFTHEMIST = 1574,
WH2WEAPON2 = 1582,
WH2BRASSKEY = 1623,
WH2BLACKKEY = 1631,
WH2GLASSKEY = 1639,
WH2IVORYKEY = 1647,
WH2NEWCHUNK = 1663,
WH2BOWLOFFIRE = 1704,
WH2SPAWNFIREBALL = 1717,
WH2PENTAGRAM = 1759,
WH2THEHORN = 1767,
WH2BOW = 1775,
WH2SWINGGATE3 = 1788,
WH2PLATEARMOR = 1793,
WH2HELMET = 1801,
WH2CHAINMAIL = 1809,
WH2SCROLLSCARE = 1817,
WH2SCROLLNUKE = 1825,
WH2SCROLLFLY = 1833,
WH2SCROLLFIREBALL = 1841,
WH2SCROLLFREEZE = 1849,
WH2SCROLLNIGHT = 1857,
WH2SCROLLMAGIC = 1865,
WH2SCROLLOPEN = 1873,
WH2LEATHERARMOR = 1881,
WH2QUIVER = 1889,
WH2SWINGGATE4 = 1897,
WH2SWINGGATE5 = 1898,
WH2SMOKEFX = 1903,
WH2STANDINTORCH = 1907,
WH2PENTADOOR3 = 1926,
WH2PENTADOOR4 = 1927,
WH2PENTADOOR5 = 1928,
WH2PENTADOOR6 = 1929,
WH2PENTADOOR7 = 1930,
WH2SCARY = 1932,
WH2FISH = 1944,
WH2LEVERUP = 1946,
WH2LEVERDOWN = 1948,
WH2SPAWNJAVLIN = 1957,
WH2RAT = 1961,
WH2GUARDIAN = 1993,
WH2GUARDIANATTACK = 2001,
WH2DART = 2009,
WH2WEAPON4 = 2026,
WH2WEAPON6 = 2038,
WH2WEAPON5 = 2046,
WH2WEAPON5B = 2054,
WH2THROWHALBERD = 2065,
WH2WEAPON7 = 2066,
WH2THROWPIKE = 2070,
WH2EXPLO2 = 2095,
WH2SHATTERVASE = 2123,
WH2SHATTERVASE2 = 2130,
WH2SHATTERVASE3 = 2137,
WH2HANGMAN = 2144,
WH2SKELETON = 2155,
WH2SKELETONATTACK = 2180,
WH2SKELETONSKULL = 2185,
WH2SKELETONUP = 2190,
WH2SKELETONDIE = 2191,
WH2SKELETONDEAD = 2197,
WH2BONECHUNK1 = 2198,
WH2BONECHUNKEND = 2207,
WH2PIKEATTACK2 = 2208,
WH2GOBWEAPON = 2217,
WH2SFLASKBLUE = 2239,
WH2SFLASKGREEN = 2240,
WH2SFLASKOCHRE = 2241,
WH2SFLASKRED = 2242,
WH2SFLASKTAN = 2243,
WH2SFLASKBLACK = 2244,
WH2SHEALTHFONT = 2245,
WH2SSCOREFONT = 2255,
WH2SPOTIONFONT = 2265,
WH2SPOTIONBACKPIC = 2279,
WH2SPOTIONARROW = 2280,
WH2SSPELLBOOKBLANK = 2285,
WH2SSPELLBOOK2 = 2293,
WH2SSPELLBOOK3 = 2301,
WH2SSPELLBOOK4 = 2309,
WH2SSPELLBOOK5 = 2316,
WH2SSPELLBOOK6 = 2323,
WH2SSPELLBOOK7 = 2331,
WH2SSPELLBOOK8 = 2339,
WH2SARROWS = 2347,
WH2SPLAYERLVL = 2348,
WH2SSTATUSBAR = 2357,
WH2SKEYBLANK = 2358,
WH2SKEYBRASS = 2359,
WH2SKEYBLACK = 2360,
WH2SKEYGLASS = 2361,
WH2SKEYIVORY = 2362,
WH2SHEALTHBACK = 2364,
WH2SSCOREBACKPIC = 2367,
WH2SNDEFFECT = 2368,
WH2SNDLOOP = 2369,
WH2SNDLOOPOFF = 2370,
WH2BROWNCHUNKSTART = 2386,
WH2GREYCHUNKSTART = 2394,
WH2REDCHUNKSTART = 2402,
WH2GREENCHUNKSTART = 2410,
WH2TANCHUNKSTART = 2418,
WH2WILLOW = 2426,
WH2SPIKES = 2487,
WH2STHEFLAG = 2490,
WH2GRONHALATTACK = 2502,
WH2GRONHALATTACKEND = 2506,
WH2GROLHALREADY = 2507,
WH2GRONHALREADYEND = 2508,
WH2GRONHAL = 2537,
WH2GRONHALPAIN = 2557,
WH2GRONHALDIE = 2558,
WH2GRONSWATTACK = 2559,
WH2GRONSW = 2579,
WH2GRONSWPAIN = 2599,
WH2GRONSWDIE = 2600,
WH2GRONMUATTACK = 2601,
WH2GRONDIE = 2631,
WH2GRONDEAD = 2637,
WH2GRONMU = 2638,
WH2GRONMUPAIN = 2658,
WH2GRONMUDIE = 2659,
WH2GRONSHIELD = 2678,
WH2SHIELD = 2682,
};
END_WH_NS