* improved physics

* Added Vorticon Elite of CK 8.4
* Reduced a bit the source code


git-svn-id: https://clonekeenplus.svn.sourceforge.net/svnroot/clonekeenplus/cgenius/trunk@163 4df4b0f3-56ce-47cb-b001-ed939b7d65a6
This commit is contained in:
gerstrong
2009-07-25 15:08:20 +00:00
parent 0958209911
commit 3044211de1
22 changed files with 357 additions and 371 deletions

View File

@@ -57,7 +57,7 @@ void ballandjack_ai(int o, stCloneKeenPlus *pCKP)
player[objects[o].touchedBy].playpushed_decreasetimer = 0; player[objects[o].touchedBy].playpushed_decreasetimer = 0;
} }
} }
else killplayer(objects[o].touchedBy, pCKP); else killplayer(objects[o].touchedBy);
} }
switch(objects[o].ai.bj.dir) switch(objects[o].ai.bj.dir)

View File

@@ -1,329 +0,0 @@
#include "../keen.h"
#include "../include/game.h"
#include "../include/enemyai.h"
#include "../sdl/sound/CSound.h"
// the "bear" enemies in ep2
// (I think the actual name for them is Vorticon Elite)
#define BEAR_WALK 0
#define BEAR_JUMP 1
#define BEAR_ABOUTTOFIRE 2
#define BEAR_FIRED 3
#define BEAR_DYING 4
#define BEAR_DEAD 5
#define BEAR_JUMP_PROB 450
#define BEAR_FIRE_PROB 400
#define BEAR_MIN_TIME_BETWEEN_FIRE 100
#define BEAR_HOLD_GUN_OUT_TIME 80
#define BEAR_HOLD_GUN_AFTER_FIRE_TIME 70
#define BEAR_MIN_JUMP_HEIGHT 15
#define BEAR_MAX_JUMP_HEIGHT 25
#define BEAR_MAX_FALL_SPEED 20
#define BEAR_JUMP_FRICTION 5
#define BEAR_JUMP_SPEED 0
#define BEAR_WALK_SPEED 5
#define BEAR_WALK_ANIM_TIME 60
// number of shots to kill
#define BEAR_HP 4
#define BEAR_DIE_ANIM_TIME 180
#define BEAR_LOOK_ANIM_TIME 60
#define BEAR_WALK_LEFT_FRAME 88
#define BEAR_WALK_RIGHT_FRAME 92
#define BEAR_JUMP_RIGHT_FRAME 98
#define BEAR_JUMP_LEFT_FRAME 99
#define BEAR_DYING_FRAME 100
#define BEAR_DEAD_FRAME 101
#define BEAR_FIRE_LEFT_FRAME 96
#define BEAR_FIRE_RIGHT_FRAME 97
#define BEAR_PALETTE_FLASH_TIME 5
#define BEAR_TRAPPED_DIST 150
int bear_walk_speed;
void bear_initiatejump(int o);
void bear_ai(int o, stLevelControl levelcontrol, stCloneKeenPlus *pCKP)
{
int bonk;
int newobject;
if (objects[o].needinit)
{ // first time initilization
objects[o].ai.bear.state = BEAR_WALK;
objects[o].ai.bear.movedir = LEFT;
objects[o].sprite = BEAR_WALK_LEFT_FRAME;
objects[o].ai.bear.frame = 0;
objects[o].ai.bear.animtimer = 0;
objects[o].ai.bear.timer = 0;
objects[o].ai.bear.timesincefire = 0;
objects[o].ai.bear.dist_traveled = BEAR_TRAPPED_DIST+1;
objects[o].ai.bear.running = 0;
objects[o].canbezapped = 1;
objects[o].needinit = 0;
}
if (objects[o].ai.bear.state==BEAR_DEAD)
{
objects[o].hasbeenonscreen = 0;
return;
}
if (objects[o].canbezapped)
{
// if we touch a glowcell, we die!
if (getmaptileat((objects[o].x>>CSF)+12, (objects[o].y>>CSF)+16)==TILE_GLOWCELL)
{
objects[o].zapped += BEAR_HP;
}
if (objects[o].zapped >= BEAR_HP)
{
objects[o].inhibitfall = 0;
objects[o].canbezapped = 0;
objects[o].ai.bear.animtimer = 0;
objects[o].ai.bear.frame = 0;
objects[o].ai.bear.state = BEAR_DYING;
if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_VORT_DIE, PLAY_NOW, objects[o].scrx);
}
}
// deadly to the touch
if (objects[o].touchPlayer && objects[o].canbezapped)
{
killplayer(objects[o].touchedBy, pCKP);
}
bear_reprocess: ;
switch(objects[o].ai.bear.state)
{
case BEAR_WALK:
objects[o].ai.bear.dist_traveled++;
if (rand()%BEAR_JUMP_PROB == (BEAR_JUMP_PROB/2) && !levelcontrol.dark && !objects[o].blockedu)
{ // let's jump.
bear_initiatejump(o);
goto bear_reprocess;
}
else
{
if (objects[o].ai.bear.timesincefire > BEAR_MIN_TIME_BETWEEN_FIRE)
{
if (rand()%BEAR_FIRE_PROB == (BEAR_FIRE_PROB/2))
{ // let's fire
// usually shoot toward keen
if (rand()%5 != 0)
{
if (objects[o].x < (objects[player[primaryplayer].useObject].x))
{
objects[o].ai.bear.movedir = RIGHT;
objects[o].ai.bear.running = 2;
}
else
{
objects[o].ai.bear.movedir = LEFT;
objects[o].ai.bear.running = 2;
}
}
objects[o].ai.bear.timer = 0;
objects[o].ai.bear.state = BEAR_ABOUTTOFIRE;
}
}
else objects[o].ai.bear.timesincefire++;
}
if (objects[o].ai.bear.movedir==LEFT)
{ // move left
objects[o].sprite = BEAR_WALK_LEFT_FRAME + objects[o].ai.bear.frame;
if (!objects[o].blockedl)
{
objects[o].x -= ((BEAR_WALK_SPEED)*(1 + objects[o].ai.bear.running));
objects[o].ai.bear.running = 0;
}
else
{
objects[o].ai.bear.movedir = RIGHT;
// if we only traveled a tiny amount before hitting a wall, we've
// probably fallen into a small narrow area, and we need to try
// to jump out of it
if (objects[o].ai.bear.dist_traveled < BEAR_TRAPPED_DIST && !levelcontrol.dark && objects[o].blockedd)
{
bear_initiatejump(o);
goto bear_reprocess;
}
else objects[o].ai.bear.dist_traveled = 0;
}
}
else
{ // move right
objects[o].sprite = BEAR_WALK_RIGHT_FRAME + objects[o].ai.bear.frame;
if (!objects[o].blockedr)
{
objects[o].x += ((BEAR_WALK_SPEED)*(1 + objects[o].ai.bear.running));
objects[o].ai.bear.running = 0;
}
else
{
objects[o].ai.bear.movedir = LEFT;
// if we only traveled a tiny amount before hitting a wall, we've
// probably fallen into a small narrow area, and we need to try
// to jump out of it
if (objects[o].ai.bear.dist_traveled < BEAR_TRAPPED_DIST && !levelcontrol.dark && objects[o].blockedd)
{
bear_initiatejump(o);
goto bear_reprocess;
}
else objects[o].ai.bear.dist_traveled = 0;
}
}
// walk animation
if (objects[o].ai.bear.animtimer > BEAR_WALK_ANIM_TIME)
{
if (objects[o].ai.bear.frame>=3) objects[o].ai.bear.frame=0;
else objects[o].ai.bear.frame++;
objects[o].ai.bear.animtimer = 0;
} else objects[o].ai.bear.animtimer++;
break;
case BEAR_JUMP:
if (objects[o].ai.bear.movedir == RIGHT)
{ if (!objects[o].blockedr) objects[o].x += ((BEAR_WALK_SPEED)*(1 + objects[o].ai.bear.running)); }
else
{ if (!objects[o].blockedl) objects[o].x -= ((BEAR_WALK_SPEED)*(1 + objects[o].ai.bear.running)); }
if (objects[o].ai.bear.inertiay>0 && objects[o].blockedd)
{ // the bear has landed
objects[o].inhibitfall = 0;
objects[o].ai.bear.state = BEAR_WALK;
goto bear_reprocess;
}
// check if the bear has bonked into a ceiling, if so,
// immediately terminate the jump
bonk = 0;
if (TileProperty[getmaptileat((objects[o].x>>CSF)+1, (objects[o].y>>CSF))][BDOWN]) bonk = 1;
else if (TileProperty[getmaptileat((objects[o].x>>CSF)+16, (objects[o].y>>CSF))][BDOWN]) bonk = 1;
else if (TileProperty[getmaptileat((objects[o].x>>CSF)+23, (objects[o].y>>CSF))][BDOWN]) bonk = 1;
/*
if (tiles[getmaptileat((objects[o].x>>CSF)+1, (objects[o].y>>CSF))].solidceil) bonk = 1;
else if (tiles[getmaptileat((objects[o].x>>CSF)+16, (objects[o].y>>CSF))].solidceil) bonk = 1;
else if (tiles[getmaptileat((objects[o].x>>CSF)+23, (objects[o].y>>CSF))].solidceil) bonk = 1;
*/
if (bonk && objects[o].ai.bear.inertiay < 0)
{
objects[o].ai.bear.inertiay = 0;
}
// apply Y inertia
objects[o].y += objects[o].ai.bear.inertiay;
if (objects[o].ai.bear.timer > BEAR_JUMP_FRICTION)
{ // slowly decrease upgoing rate
if (objects[o].ai.bear.inertiay<BEAR_MAX_FALL_SPEED)
{
objects[o].ai.bear.inertiay++;
}
objects[o].ai.bear.timer = 0;
} else objects[o].ai.bear.timer++;
break;
case BEAR_ABOUTTOFIRE:
if (objects[o].ai.bear.movedir==RIGHT)
{ objects[o].sprite = BEAR_FIRE_RIGHT_FRAME; }
else
{ objects[o].sprite = BEAR_FIRE_LEFT_FRAME; }
if (objects[o].ai.bear.timer > BEAR_HOLD_GUN_OUT_TIME)
{
objects[o].ai.bear.timer = 0;
objects[o].ai.bear.state = BEAR_FIRED;
if (objects[o].ai.bear.movedir==RIGHT)
{
newobject = spawn_object(objects[o].x+(sprites[BEAR_FIRE_RIGHT_FRAME].xsize<<CSF), objects[o].y+(9<<CSF), OBJ_RAY);
objects[newobject].ai.ray.direction = RIGHT;
}
else
{
newobject = spawn_object(objects[o].x-(sprites[ENEMYRAYEP2].xsize<<CSF), objects[o].y+(9<<CSF), OBJ_RAY);
objects[newobject].ai.ray.direction = LEFT;
}
objects[newobject].sprite = ENEMYRAYEP2;
// don't shoot other bears
objects[newobject].ai.ray.dontHitEnable = 1;
objects[newobject].ai.ray.dontHit = OBJ_BEAR;
if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_KEEN_FIRE, PLAY_NOW, objects[o].scrx);
}
else objects[o].ai.bear.timer++;
break;
case BEAR_FIRED:
if (objects[o].ai.bear.movedir==RIGHT)
{ objects[o].sprite = BEAR_FIRE_RIGHT_FRAME; }
else
{ objects[o].sprite = BEAR_FIRE_LEFT_FRAME; }
if (objects[o].ai.bear.timer > BEAR_HOLD_GUN_AFTER_FIRE_TIME)
{
objects[o].ai.bear.timer = 0;
objects[o].ai.bear.frame = 0;
objects[o].ai.bear.timesincefire = 0;
objects[o].ai.bear.state = BEAR_WALK;
// head toward keen
if (objects[o].x < player[primaryplayer].x)
{
objects[o].ai.bear.movedir = RIGHT;
}
else
{
objects[o].ai.bear.movedir = LEFT;
}
}
else objects[o].ai.bear.timer++;
break;
case BEAR_DYING:
objects[o].sprite = BEAR_DYING_FRAME;
if (objects[o].ai.bear.animtimer > BEAR_DIE_ANIM_TIME)
{
objects[o].sprite = BEAR_DEAD_FRAME;
objects[o].ai.bear.state = BEAR_DEAD;
}
else
{
objects[o].ai.bear.animtimer++;
}
break;
default: break;
}
}
void bear_initiatejump(int o)
{
if (objects[o].ai.bear.state==BEAR_JUMP) return;
objects[o].ai.bear.frame = 0;
objects[o].ai.bear.animtimer = 0;
objects[o].ai.bear.inertiay = \
-((rand()%(BEAR_MAX_JUMP_HEIGHT-BEAR_MIN_JUMP_HEIGHT))+BEAR_MIN_JUMP_HEIGHT);
if (objects[o].ai.bear.movedir==RIGHT)
{
objects[o].sprite = BEAR_JUMP_RIGHT_FRAME;
}
else
{
objects[o].sprite = BEAR_JUMP_LEFT_FRAME;
}
objects[o].inhibitfall = 1;
objects[o].ai.bear.state = BEAR_JUMP;
}

View File

@@ -53,7 +53,7 @@ void fireball_ai(int o, stCloneKeenPlus *pCKP)
// check if it hit keen // check if it hit keen
if (objects[o].touchPlayer) if (objects[o].touchPlayer)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
objects[o].type = OBJ_RAY; objects[o].type = OBJ_RAY;
objects[o].ai.ray.state = RAY_STATE_SETZAPZOT; objects[o].ai.ray.state = RAY_STATE_SETZAPZOT;
objects[o].inhibitfall = 1; objects[o].inhibitfall = 1;

View File

@@ -56,7 +56,7 @@ unsigned int i;
if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_YORP_DIE, PLAY_NOW, objects[o].scrx); if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_YORP_DIE, PLAY_NOW, objects[o].scrx);
if (pCKP->Control.levelcontrol.hardmode && objects[o].touchPlayer) if (pCKP->Control.levelcontrol.hardmode && objects[o].touchPlayer)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
} }
} }

View File

@@ -60,7 +60,7 @@ unsigned int i;
// kill player on touch // kill player on touch
if (objects[o].ai.garg.state!=GARG_DYING && objects[o].touchPlayer) if (objects[o].ai.garg.state!=GARG_DYING && objects[o].touchPlayer)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
// did the garg get shot? // did the garg get shot?

View File

@@ -54,7 +54,7 @@ int onsamelevel;
if (objects[o].touchPlayer && !player[objects[o].touchedBy].pdie && \ if (objects[o].touchPlayer && !player[objects[o].touchedBy].pdie && \
objects[o].ai.ninja.state != NINJA_DYING) objects[o].ai.ninja.state != NINJA_DYING)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
if (objects[o].zapped >= 4) if (objects[o].zapped >= 4)

View File

@@ -72,7 +72,7 @@ int hitlethal;
{ {
if (objects[o].ai.ray.dontHitEnable==0 || objects[o].ai.ray.dontHit!=OBJ_PLAYER) if (objects[o].ai.ray.dontHitEnable==0 || objects[o].ai.ray.dontHit!=OBJ_PLAYER)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
objects[o].ai.ray.state = RAY_STATE_SETZAPZOT; objects[o].ai.ray.state = RAY_STATE_SETZAPZOT;
} }
} }

View File

@@ -563,7 +563,7 @@ int newobject;
// deadly to the touch // deadly to the touch
if (objects[o].touchPlayer) if (objects[o].touchPlayer)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
if (objects[o].ai.se.timer > SPARK_ANIMRATE) if (objects[o].ai.se.timer > SPARK_ANIMRATE)
@@ -959,7 +959,7 @@ void se_mortimer_leg_right(int o, stCloneKeenPlus *pCKP)
int mx,my; int mx,my;
if (objects[o].touchPlayer) if (objects[o].touchPlayer)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
if (objects[o].needinit) if (objects[o].needinit)
{ {

View File

@@ -29,7 +29,7 @@ void sndwave_ai(int o, stCloneKeenPlus *pCKP)
// check if it hit keen // check if it hit keen
if (objects[o].touchPlayer) if (objects[o].touchPlayer)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
// destroy the sound wave if it's been offscreen for a good amount // destroy the sound wave if it's been offscreen for a good amount

View File

@@ -64,7 +64,7 @@ unsigned int i;
// touched player? // touched player?
if (objects[o].touchPlayer && !player[objects[o].touchedBy].pdie) if (objects[o].touchPlayer && !player[objects[o].touchedBy].pdie)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
switch(objects[o].ai.tank.state) switch(objects[o].ai.tank.state)

View File

@@ -133,7 +133,7 @@ int bonk,kill;
// deadly to the touch // deadly to the touch
if (objects[o].touchPlayer && objects[o].canbezapped) if (objects[o].touchPlayer && objects[o].canbezapped)
{ {
killplayer(objects[o].touchedBy, pCKP); killplayer(objects[o].touchedBy);
} }
vort_reprocess: ; vort_reprocess: ;

311
src/ai/vortelite.cpp Normal file
View File

@@ -0,0 +1,311 @@
#include "../keen.h"
#include "vortelite.h"
#include "../include/game.h"
#include "../sdl/sound/CSound.h"
// the "Vorticon Elite" enemies in ep2
#define VORTELITE_WALK 0
#define VORTELITE_JUMP 1
#define VORTELITE_ABOUTTOFIRE 2
#define VORTELITE_FIRED 3
#define VORTELITE_DYING 4
#define VORTELITE_DEAD 5
#define VORTELITE_JUMP_PROB 400
#define VORTELITE_FIRE_PROB 320
#define VORTELITE_MIN_TIME_BETWEEN_FIRE 100
#define VORTELITE_HOLD_GUN_OUT_TIME 90
#define VORTELITE_HOLD_GUN_AFTER_FIRE_TIME 75
#define VORTELITE_MIN_JUMP_HEIGHT 15
#define VORTELITE_MAX_JUMP_HEIGHT 25
#define VORTELITE_MAX_FALL_SPEED 20
#define VORTELITE_JUMP_FRICTION 6
#define VORTELITE_WALK_SPEED 7
#define VORTELITE_WALK_ANIM_TIME 50
// number of shots to kill
#define VORTELITE_HP 4
#define VORTELITE_DIE_ANIM_TIME 180
#define VORTELITE_LOOK_ANIM_TIME 60
#define VORTELITE_WALK_LEFT_FRAME 88
#define VORTELITE_WALK_RIGHT_FRAME 92
#define VORTELITE_JUMP_RIGHT_FRAME 98
#define VORTELITE_JUMP_LEFT_FRAME 99
#define VORTELITE_DYING_FRAME 100
#define VORTELITE_DEAD_FRAME 101
#define VORTELITE_FIRE_LEFT_FRAME 96
#define VORTELITE_FIRE_RIGHT_FRAME 97
#define VORTELITE_PALETTE_FLASH_TIME 5
#define VORTELITE_TRAPPED_DIST 150
void vortelite_initiatejump(int o);
void vortelite_ai(int o, bool darkness)
{
int bonk;
int newobject;
if (objects[o].needinit)
{ // first time initilization
objects[o].ai.vortelite.state = VORTELITE_WALK;
objects[o].ai.vortelite.movedir = LEFT;
objects[o].sprite = VORTELITE_WALK_LEFT_FRAME;
objects[o].ai.vortelite.frame = 0;
objects[o].ai.vortelite.animtimer = 0;
objects[o].ai.vortelite.timer = 0;
objects[o].ai.vortelite.timesincefire = 0;
objects[o].ai.vortelite.dist_traveled = VORTELITE_TRAPPED_DIST+1;
objects[o].canbezapped = 1;
objects[o].needinit = 0;
}
if (objects[o].ai.vortelite.state==VORTELITE_DEAD)
{
objects[o].hasbeenonscreen = 0;
return;
}
if (objects[o].canbezapped)
{
// if we touch a glowcell, we die!
if (getmaptileat((objects[o].x>>CSF)+12, (objects[o].y>>CSF)+16)==TILE_GLOWCELL)
{
objects[o].zapped += VORTELITE_HP;
}
if (objects[o].zapped >= VORTELITE_HP)
{
objects[o].inhibitfall = 0;
objects[o].canbezapped = 0;
objects[o].ai.vortelite.animtimer = 0;
objects[o].ai.vortelite.frame = 0;
objects[o].ai.vortelite.state = VORTELITE_DYING;
if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_VORT_DIE, PLAY_NOW, objects[o].scrx);
}
}
// deadly to the touch
if (objects[o].touchPlayer && objects[o].canbezapped)
{
killplayer(objects[o].touchedBy);
}
reprocess: ;
switch(objects[o].ai.vortelite.state)
{
case VORTELITE_WALK:
objects[o].ai.vortelite.dist_traveled++;
if (rand()%VORTELITE_JUMP_PROB == (VORTELITE_JUMP_PROB/2) && !darkness && !objects[o].blockedu)
{ // let's jump.
vortelite_initiatejump(o);
goto reprocess;
}
else
{
if (objects[o].ai.vortelite.timesincefire > VORTELITE_MIN_TIME_BETWEEN_FIRE)
{
if (rnd()%VORTELITE_FIRE_PROB == (VORTELITE_FIRE_PROB/2))
{ // let's fire
// usually shoot toward keen
if (rnd()%5 != 0)
{
if (objects[o].x < player[primaryplayer].x)
{
objects[o].ai.vortelite.movedir = RIGHT;
}
else
{
objects[o].ai.vortelite.movedir = LEFT;
}
}
objects[o].ai.vortelite.timer = 0;
objects[o].ai.vortelite.state = VORTELITE_ABOUTTOFIRE;
}
}
else objects[o].ai.vortelite.timesincefire++;
}
if (objects[o].ai.vortelite.movedir==LEFT)
{ // move left
objects[o].sprite = VORTELITE_WALK_LEFT_FRAME + objects[o].ai.vortelite.frame;
if (!objects[o].blockedl)
{
objects[o].x -= VORTELITE_WALK_SPEED;
}
else
{
objects[o].ai.vortelite.movedir = RIGHT;
// if we only traveled a tiny amount before hitting a wall, we've
// probably fallen into a small narrow area, and we need to try
// to jump out of it
if (objects[o].ai.vortelite.dist_traveled < VORTELITE_TRAPPED_DIST && !darkness && objects[o].blockedd)
{
vortelite_initiatejump(o);
goto reprocess;
}
else objects[o].ai.vortelite.dist_traveled = 0;
}
}
else
{ // move right
objects[o].sprite = VORTELITE_WALK_RIGHT_FRAME + objects[o].ai.vortelite.frame;
if (!objects[o].blockedr)
{
objects[o].x += VORTELITE_WALK_SPEED;
}
else
{
objects[o].ai.vortelite.movedir = LEFT;
// if we only traveled a tiny amount before hitting a wall, we've
// probably fallen into a small narrow area, and we need to try
// to jump out of it
if (objects[o].ai.vortelite.dist_traveled < VORTELITE_TRAPPED_DIST && !darkness && objects[o].blockedd)
{
vortelite_initiatejump(o);
goto reprocess;
}
else objects[o].ai.vortelite.dist_traveled = 0;
}
}
// walk animation
if (objects[o].ai.vortelite.animtimer > VORTELITE_WALK_ANIM_TIME)
{
if (objects[o].ai.vortelite.frame>=3) objects[o].ai.vortelite.frame=0;
else objects[o].ai.vortelite.frame++;
objects[o].ai.vortelite.animtimer = 0;
} else objects[o].ai.vortelite.animtimer++;
break;
case VORTELITE_JUMP:
if (objects[o].ai.vortelite.movedir == RIGHT)
{ if (!objects[o].blockedr) objects[o].x += VORTELITE_WALK_SPEED; }
else
{ if (!objects[o].blockedl) objects[o].x -= VORTELITE_WALK_SPEED; }
if (objects[o].ai.vortelite.inertiay>0 && objects[o].blockedd)
{ // the bear has landed
objects[o].inhibitfall = 0;
objects[o].ai.vortelite.state = VORTELITE_WALK;
goto reprocess;
}
// check if the bear has bonked into a ceiling, if so,
// immediately terminate the jump
bonk = 0;
if (TileProperty[getmaptileat((objects[o].x>>CSF)+1, (objects[o].y>>CSF))][BDOWN]) bonk = 1;
else if (TileProperty[getmaptileat((objects[o].x>>CSF)+16, (objects[o].y>>CSF))][BDOWN]) bonk = 1;
else if (TileProperty[getmaptileat((objects[o].x>>CSF)+23, (objects[o].y>>CSF))][BDOWN]) bonk = 1;
if (bonk && objects[o].ai.vortelite.inertiay < 0)
{
objects[o].ai.vortelite.inertiay = 0;
}
// apply Y inertia
objects[o].y += objects[o].ai.vortelite.inertiay;
if (objects[o].ai.vortelite.timer > VORTELITE_JUMP_FRICTION)
{ // slowly decrease upgoing rate
if (objects[o].ai.vortelite.inertiay<VORTELITE_MAX_FALL_SPEED)
{
objects[o].ai.vortelite.inertiay++;
}
objects[o].ai.vortelite.timer = 0;
} else objects[o].ai.vortelite.timer++;
break;
case VORTELITE_ABOUTTOFIRE:
if (objects[o].ai.vortelite.movedir==RIGHT)
{ objects[o].sprite = VORTELITE_FIRE_RIGHT_FRAME; }
else
{ objects[o].sprite = VORTELITE_FIRE_LEFT_FRAME; }
if (objects[o].ai.vortelite.timer > VORTELITE_HOLD_GUN_OUT_TIME)
{
objects[o].ai.vortelite.timer = 0;
objects[o].ai.vortelite.state = VORTELITE_FIRED;
if (objects[o].ai.vortelite.movedir==RIGHT)
{
newobject = spawn_object(objects[o].x+(sprites[VORTELITE_FIRE_RIGHT_FRAME].xsize<<CSF), objects[o].y+(9<<CSF), OBJ_RAY);
objects[newobject].ai.ray.direction = RIGHT;
}
else
{
newobject = spawn_object(objects[o].x-(sprites[ENEMYRAYEP2].xsize<<CSF), objects[o].y+(9<<CSF), OBJ_RAY);
objects[newobject].ai.ray.direction = LEFT;
}
objects[newobject].sprite = ENEMYRAYEP2;
// don't shoot other vorticon elite
objects[newobject].ai.ray.dontHitEnable = 1;
objects[newobject].ai.ray.dontHit = OBJ_VORTELITE;
if (objects[o].onscreen) g_pSound->playStereofromCoord(SOUND_KEEN_FIRE, PLAY_NOW, objects[o].scrx);
}
else objects[o].ai.vortelite.timer++;
break;
case VORTELITE_FIRED:
if (objects[o].ai.vortelite.movedir==RIGHT)
{ objects[o].sprite = VORTELITE_FIRE_RIGHT_FRAME; }
else
{ objects[o].sprite = VORTELITE_FIRE_LEFT_FRAME; }
if (objects[o].ai.vortelite.timer > VORTELITE_HOLD_GUN_AFTER_FIRE_TIME)
{
objects[o].ai.vortelite.timer = 0;
objects[o].ai.vortelite.frame = 0;
objects[o].ai.vortelite.timesincefire = 0;
objects[o].ai.vortelite.state = VORTELITE_WALK;
// head toward keen
if (objects[o].x < player[primaryplayer].x)
{
objects[o].ai.vortelite.movedir = RIGHT;
}
else
{
objects[o].ai.vortelite.movedir = LEFT;
}
}
else objects[o].ai.vortelite.timer++;
break;
case VORTELITE_DYING:
objects[o].sprite = VORTELITE_DYING_FRAME;
if (objects[o].ai.vortelite.animtimer > VORTELITE_DIE_ANIM_TIME)
{
objects[o].sprite = VORTELITE_DEAD_FRAME;
objects[o].ai.vortelite.state = VORTELITE_DEAD;
}
else
{
objects[o].ai.vortelite.animtimer++;
}
break;
default: break;
}
}
void vortelite_initiatejump(int o)
{
if (objects[o].ai.vortelite.state==VORTELITE_JUMP) return;
objects[o].ai.vortelite.frame = 0;
objects[o].ai.vortelite.animtimer = 0;
objects[o].ai.vortelite.inertiay = \
-((rnd()%(VORTELITE_MAX_JUMP_HEIGHT-VORTELITE_MIN_JUMP_HEIGHT))+VORTELITE_MIN_JUMP_HEIGHT);
if (objects[o].ai.vortelite.movedir==RIGHT)
{
objects[o].sprite = VORTELITE_JUMP_RIGHT_FRAME;
}
else
{
objects[o].sprite = VORTELITE_JUMP_LEFT_FRAME;
}
objects[o].inhibitfall = 1;
objects[o].ai.vortelite.state = VORTELITE_JUMP;
}

View File

@@ -285,7 +285,7 @@ int o,x;
} }
else if (pCKP->Control.levelcontrol.episode==2) else if (pCKP->Control.levelcontrol.episode==2)
{ {
spawn_object(curmapx<<4<<CSF, curmapy<<4<<CSF, OBJ_BEAR); spawn_object(curmapx<<4<<CSF, curmapy<<4<<CSF, OBJ_VORTELITE);
} }
else if (pCKP->Control.levelcontrol.episode==3) else if (pCKP->Control.levelcontrol.episode==3)
{ {

View File

@@ -75,7 +75,7 @@ void gameloop(stCloneKeenPlus *pCKP)
{ {
for(i=0;i<MAX_PLAYERS;i++) for(i=0;i<MAX_PLAYERS;i++)
{ {
if (player[i].isPlaying) gamepdo_SelectFrame(i, pCKP); if (player[i].isPlaying) gamepdo_SelectFrame(i);
} }
do do
@@ -415,7 +415,7 @@ int mpx,mpy,t;
else if (TileProperty[t][BEHAVIOR] == 1) else if (TileProperty[t][BEHAVIOR] == 1)
//else if (tiles[t].lethal) //else if (tiles[t].lethal)
{ // whoah, this "goodie" isn't so good... { // whoah, this "goodie" isn't so good...
killplayer(theplayer, pCKP); killplayer(theplayer);
return; return;
} }
@@ -491,7 +491,7 @@ unsigned int i;
{ {
objdefsprites[OBJ_WALKER] = OBJ_WALKER_DEFSPRITE; objdefsprites[OBJ_WALKER] = OBJ_WALKER_DEFSPRITE;
objdefsprites[OBJ_TANKEP2] = OBJ_TANKEP2_DEFSPRITE; objdefsprites[OBJ_TANKEP2] = OBJ_TANKEP2_DEFSPRITE;
objdefsprites[OBJ_BEAR] = OBJ_BEAR_DEFSPRITE; objdefsprites[OBJ_VORTELITE] = OBJ_VORTELITE_DEFSPRITE;
objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP2; objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP2;
objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP2; objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP2;
@@ -837,11 +837,10 @@ unsigned int rect2x1, rect2y1, rect2x2, rect2y2;
return 1; return 1;
} }
void killplayer(int theplayer, stCloneKeenPlus *pCKP) void killplayer(int theplayer)
{ {
if (player[theplayer].godmode || g_pInput->getHoldedKey(KTAB)) return; if (player[theplayer].godmode || g_pInput->getHoldedKey(KTAB)) return;
if (player[theplayer].ankhtime) return; if (player[theplayer].ankhtime) return;
if (pCKP->Control.levelcontrol.level_done) return;
if (!player[theplayer].pdie) if (!player[theplayer].pdie)
{ {
player[theplayer].pdie = PDIE_DYING; player[theplayer].pdie = PDIE_DYING;
@@ -852,7 +851,7 @@ void killplayer(int theplayer, stCloneKeenPlus *pCKP)
player[theplayer].pdie_xvect -= DIE_MAX_XVECT; player[theplayer].pdie_xvect -= DIE_MAX_XVECT;
player[theplayer].inventory.lives--; player[theplayer].inventory.lives--;
player[theplayer].y += (8<<CSF); player[theplayer].y += (8<<CSF);
gamepdo_SelectFrame(theplayer, pCKP); gamepdo_SelectFrame(theplayer);
g_pMusicPlayer->stop(); g_pMusicPlayer->stop();
g_pSound->playSound(SOUND_KEEN_DIE, PLAY_NOW); g_pSound->playSound(SOUND_KEEN_DIE, PLAY_NOW);
} }

View File

@@ -266,7 +266,7 @@ int i;
case OBJ_WALKER: walker_ai(i, pCKP->Control.levelcontrol); break; case OBJ_WALKER: walker_ai(i, pCKP->Control.levelcontrol); break;
case OBJ_TANKEP2: tankep2_ai(i, pCKP); break; case OBJ_TANKEP2: tankep2_ai(i, pCKP); break;
case OBJ_PLATFORM: platform_ai(i, pCKP->Control.levelcontrol); break; case OBJ_PLATFORM: platform_ai(i, pCKP->Control.levelcontrol); break;
case OBJ_BEAR: bear_ai(i, pCKP->Control.levelcontrol, pCKP); break; case OBJ_VORTELITE: vortelite_ai(i, pCKP->Control.levelcontrol.dark); break;
case OBJ_SECTOREFFECTOR: se_ai(i, pCKP); break; case OBJ_SECTOREFFECTOR: se_ai(i, pCKP); break;
case OBJ_BABY: baby_ai(i, pCKP->Control.levelcontrol); break; case OBJ_BABY: baby_ai(i, pCKP->Control.levelcontrol); break;
case OBJ_EXPLOSION: explosion_ai(i); break; case OBJ_EXPLOSION: explosion_ai(i); break;

View File

@@ -97,7 +97,7 @@ char doFall;
} }
} }
gamepdo_SelectFrame(cp, pCKP); gamepdo_SelectFrame(cp);
} }
void gamepdo_walkbehindexitdoor(int cp, stCloneKeenPlus *pCKP) void gamepdo_walkbehindexitdoor(int cp, stCloneKeenPlus *pCKP)
@@ -131,7 +131,7 @@ void gamepdo_dieanim(int cp, stCloneKeenPlus *pCKP)
if (!g_pSound->isPlaying(SOUND_KEEN_FALL)) if (!g_pSound->isPlaying(SOUND_KEEN_FALL))
{ {
player[cp].pdie = 0; player[cp].pdie = 0;
killplayer(cp, pCKP); killplayer(cp);
} }
else return; else return;
} }
@@ -368,7 +368,7 @@ void gamepdo_setblockedlru(unsigned int cp, stCloneKeenPlus *pCKP)
if((TileProperty[getmaptileat(tx,ty)][BUP] == 1) && (TileProperty[getmaptileat(tx,ty)][BEHAVIOR] == 1)) if((TileProperty[getmaptileat(tx,ty)][BUP] == 1) && (TileProperty[getmaptileat(tx,ty)][BEHAVIOR] == 1))
{ {
killplayer(cp,pCKP); // Whines killplayer(cp); // Whines
} }
// set psliding if we're on ice // set psliding if we're on ice
@@ -647,7 +647,7 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
} }
else else
{ {
player[cp].pboost_x-= player[cp].ppogostick ? 2 : 1; player[cp].pboost_x-= player[cp].ppogostick ? 3 : 1;
} }
} }
if (player[cp].playcontrol[PA_X] > 0 && !player[cp].pfrozentime) if (player[cp].playcontrol[PA_X] > 0 && !player[cp].pfrozentime)
@@ -659,7 +659,7 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
} }
else else
{ {
player[cp].pboost_x+= player[cp].ppogostick ? 2 : 1; player[cp].pboost_x+= player[cp].ppogostick ? 3 : 1;
} }
} }
@@ -1321,7 +1321,6 @@ short tilsupport;
// before you land turn around and as you hit the ground // before you land turn around and as you hit the ground
// you're starting to move the other direction // you're starting to move the other direction
// (set inertia to 0 if it's contrary to player's current dir) // (set inertia to 0 if it's contrary to player's current dir)
} }
@@ -1438,7 +1437,7 @@ int canRefire;
} }
// select the appropriate player frame based on what he's doing // select the appropriate player frame based on what he's doing
void gamepdo_SelectFrame(int cp, stCloneKeenPlus *pCKP) void gamepdo_SelectFrame(int cp)
{ {
player[cp].playframe = 0; // basic standing player[cp].playframe = 0; // basic standing

View File

@@ -46,7 +46,7 @@ struct stLevelControl
char canexit; // 1 if player is allowed to use the exit door char canexit; // 1 if player is allowed to use the exit door
char gameovermode; // 1 if "Game Over" is displayed char gameovermode; // 1 if "Game Over" is displayed
char dokeensleft; // 1 if we need to do the "Keens Left" char dokeensleft; // 1 if we need to do the "Keens Left"
char dark; // 1 if level is currently dark (lights are out) bool dark; // true if level is currently dark (lights are out)
int episode; // which episode we're playing (1-3) int episode; // which episode we're playing (1-3)
bool hardmode; bool hardmode;

View File

@@ -22,7 +22,7 @@ void rope_ai(int o);
void walker_ai(int o, stLevelControl levelcontrol); void walker_ai(int o, stLevelControl levelcontrol);
void tankep2_ai(int o, stCloneKeenPlus *pCKP); void tankep2_ai(int o, stCloneKeenPlus *pCKP);
void platform_ai(int o, stLevelControl levelcontrol); void platform_ai(int o, stLevelControl levelcontrol);
void bear_ai(int o, stLevelControl levelcontrol, stCloneKeenPlus *pCKP); void vortelite_ai(int o, bool darkness);
void se_ai(int o, stCloneKeenPlus *pCKP); void se_ai(int o, stCloneKeenPlus *pCKP);
void baby_ai(int o, stLevelControl levelcontrol); void baby_ai(int o, stLevelControl levelcontrol);
void explosion_ai(int o); void explosion_ai(int o);

View File

@@ -218,7 +218,7 @@ void initgame(stCloneKeenPlus *pCKP);
int initgamefirsttime(stCloneKeenPlus *pCKP, int s); int initgamefirsttime(stCloneKeenPlus *pCKP, int s);
void open_door(int doortile, int doorsprite, int mpx, int mpy, int cp, stCloneKeenPlus *pCKP); void open_door(int doortile, int doorsprite, int mpx, int mpy, int cp, stCloneKeenPlus *pCKP);
void killplayer(int theplayer, stCloneKeenPlus *pCKP); void killplayer(int theplayer);
void PlayerTouchedExit(int theplayer, stCloneKeenPlus *pCKP); void PlayerTouchedExit(int theplayer, stCloneKeenPlus *pCKP);
void endlevel(int success, stCloneKeenPlus *pCKP); void endlevel(int success, stCloneKeenPlus *pCKP);

View File

@@ -20,7 +20,7 @@ void gamepdo_Jump(int cp);
//void gamepdo_falling(int cp, stCommand command[MAX_COMMANDS]); //void gamepdo_falling(int cp, stCommand command[MAX_COMMANDS]);
void gamepdo_raygun(int cp, stCloneKeenPlus *pCKP); void gamepdo_raygun(int cp, stCloneKeenPlus *pCKP);
void gamepdo_special(int cp, stCloneKeenPlus *pCKP); void gamepdo_special(int cp, stCloneKeenPlus *pCKP);
void gamepdo_SelectFrame(int cp, stCloneKeenPlus *pCKP); void gamepdo_SelectFrame(int cp);
void gamepdo_checkcollision(int cp, stCloneKeenPlus *pCKP); void gamepdo_checkcollision(int cp, stCloneKeenPlus *pCKP);
void gamepdo_moveplayer(int cp, stCloneKeenPlus *pCKP); void gamepdo_moveplayer(int cp, stCloneKeenPlus *pCKP);
void gamepdo_ankh(int cp); void gamepdo_ankh(int cp);

View File

@@ -1,15 +1,10 @@
#ifndef __KEEN_H__
#define __KEEN_H__
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#ifdef TARGET_DOS
#include <dpmi.h>
#include <sys/farptr.h>
#include <go32.h>
#include <dos.h>
#include "dos\timer.h"
#endif
#ifdef TARGET_WIN32 #ifdef TARGET_WIN32
#include <windows.h> #include <windows.h>
#endif #endif
@@ -222,7 +217,7 @@ struct stVortData
int DeadFrame; int DeadFrame;
}; };
struct stBearData struct stVortEliteData
{ {
unsigned char state; unsigned char state;
@@ -517,7 +512,7 @@ typedef struct stObject
// ep2 // ep2
stWalkerData walker; stWalkerData walker;
stPlatformData platform; stPlatformData platform;
stBearData bear; stVortEliteData vortelite;
stSEData se; stSEData se;
stBabyData baby; stBabyData baby;
// ep3 // ep3
@@ -562,7 +557,7 @@ typedef struct stAnimTile
#define OBJ_WALKER 13 #define OBJ_WALKER 13
#define OBJ_TANKEP2 14 #define OBJ_TANKEP2 14
#define OBJ_PLATFORM 15 #define OBJ_PLATFORM 15
#define OBJ_BEAR 16 #define OBJ_VORTELITE 16
#define OBJ_SECTOREFFECTOR 17 #define OBJ_SECTOREFFECTOR 17
#define OBJ_BABY 18 #define OBJ_BABY 18
#define OBJ_EXPLOSION 19 #define OBJ_EXPLOSION 19
@@ -608,7 +603,7 @@ typedef struct stAnimTile
#define OBJ_PLATFORM_DEFSPRITE_EP3 107 #define OBJ_PLATFORM_DEFSPRITE_EP3 107
#define OBJ_WALKER_DEFSPRITE 102 #define OBJ_WALKER_DEFSPRITE 102
#define OBJ_TANKEP2_DEFSPRITE 112 #define OBJ_TANKEP2_DEFSPRITE 112
#define OBJ_BEAR_DEFSPRITE 88 #define OBJ_VORTELITE_DEFSPRITE 88
#define OBJ_FOOB_DEFSPRITE 95 #define OBJ_FOOB_DEFSPRITE 95
#define OBJ_NINJA_DEFSPRITE 77 #define OBJ_NINJA_DEFSPRITE 77
@@ -878,3 +873,5 @@ struct stCloneKeenPlus
// keen.c // keen.c
void playgame_levelmanager(stCloneKeenPlus *pCKP); void playgame_levelmanager(stCloneKeenPlus *pCKP);
char play_demo(int demonum, stCloneKeenPlus *pCKP, int s); char play_demo(int demonum, stCloneKeenPlus *pCKP, int s);
#endif

View File

@@ -1102,6 +1102,15 @@ int dlgX,dlgY,dlgW,dlgH;
} while(1); } while(1);
} }
// a random number generator
ulong random_seed;
void srnd(ulong newseed) { random_seed = newseed; }
uint rnd(void)
{
random_seed = random_seed * 1103515245 + 12345;
return (uint)(random_seed / 65536) % 32768;
}
int endsequence(stCloneKeenPlus *pCKP) int endsequence(stCloneKeenPlus *pCKP)
{ {