kaos/KaosSrc/objects2.cpp
2024-10-12 20:32:30 -05:00

2484 lines
No EOL
66 KiB
C++

/************************************************************************
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
************************************************************************/
// OBJECTS2 - (C)1997 NicoSoŸt (Valentini Domenico)
#include "std.hpp"
#include "fastmem.hpp"
#include "fixed.h"
#include "events.hpp"
#include "mm4.hpp" // per Kaos.hpp
#include "crcio.hpp"
#include "kaos.hpp"
#include "objects.hpp"
#include "objects2.hpp"
#include "3dengine.hpp"
#include "3dsound.hpp"
#include "doors.hpp"
#include "messages.hpp"
#include <stdlib.h> // per random()...
//#include <dos.h> // sound() !!!
// Ehi, un po' in ritardo.
char Object::doblood(int angle) {
int oppangle;
fixed x,y;
if (!(figstart>=F_PLAYER && figstart<=F_MOUSE)) return 0;
oppangle = angleadd(angle,ANG180);
x = mover->x + fixmul(costab[oppangle],FIXONE<<mover->shdim);
y = mover->y + fixmul(sintab[oppangle],FIXONE<<mover->shdim);
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(x,y,mover->z,oppangle,BOOM_BLOOD));
if (figstart<F_MOUSE) {
fixed dist, z = mover->z;
// !!!! vangle usato impropriamente (o Š angle ???) !!!
int id1 = fireray(x,y,angle,ANG0,dist,z,mover->id);
if (id1==-1 && dist<(128l<<FIXSHIFT))
eventmanager.sendshort(EV_CHGTEXTURE,0,0,xytoidx(x,y),0);
}
return 1;
}
Ossa::Ossa(fixed px, fixed py, int type)
:Actor(px,py,type,1,MVT_0)
{
object_type=OBJT_OSSA;
if (type == F_OSSALIT) {
SETFLAG(oflags,OFL_TAKEABLE);
mover->flags = OMF_VISIBLE;
}
animtrig=0;
}
Ossa::Ossa(int handle)
:Actor(handle) {
animtrig=0;
}
void Ossa::animate() {
if (--animtrig<=0) makeObject();
}
void Ossa::launch(int angle, int strong) {
if (!animtrig) {
animtrig = 2;
makeActor();
delete mm_reserve(sizeof(FlOssa));
if (!GETFLAG(gameflags,GFL_NORANDOM))
angle = anglesub(angleadd(angle,ANG30>>1),random(ANG30));
objectslist.put(new FlOssa(mover->x,mover->y,angle,strong));
play3Dsound(mover->x,mover->y,SND_OSSA,SM_NORMVOL,SYSOWN,SFL_NORMAL);
} else animtrig++;
}
void Ossa::handle_event(TEvent &event) {
if (event.what != EV_GOT) Object::handle_event(event);
switch (event.what) {
case EV_HIT:
case EV_GOT:
launch(event.data.msg.x,event.data.msg.y);
//if (random(5)==2) launch(event.data.msg.x,event.data.msg.y);
break;
}
}
FlOssa::FlOssa(fixed px, fixed py, int angle, int _speed)
:Actor(px,py,F_TESCHIO+random(2),1,MVT_1)
{
object_type=OBJT_FLOSSA;
if (_speed>24) speed=24; else speed=_speed;
mover->angle = angle;
mover->shdim = 3;
mover->flags = OMF_VISIBLE;
bang = 0;
}
FlOssa::FlOssa(int handle)
:Actor(handle) {
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&bang,sizeof(bang));
}
void FlOssa::save(int handle) {
Actor::save(handle);
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&bang,sizeof(bang));
}
void FlOssa::animate() {
Mover &mv = *mover;
if (speed>0) {
remove();
fixed nx = mv.x + (costab[mv.angle]*(speed>>1)),
ny = mv.y + (sintab[mv.angle]*(speed>>1));
if (!mv.canmove(nx,mv.y)) {
if (mv.angle<=ANG180) mv.angle=ANG180-mv.angle;
else mv.angle=ANG180+ANG360-mv.angle;
} else mv.x = nx;
if (!mv.canmove(mv.x,ny)) {
if (mv.angle!=ANG0) mv.angle=ANG360-mv.angle;
} else mv.y = ny;
bang = angleadd(bang,(12-(speed>>1))<<5);
mv.z = LABS(fixmul(lshl16(speed),sintab[bang]));
/*
oldz = mv.z;
if ((mv.z = (6l<<16)+LABS(fixmul(lshl16(speed),sintab[bang])))>oldz)
play3Dsound(mover->x,mover->y,SND_TESCHIO,0,0,mover->id,SFL_AUTO);
*/
place();
speed--;
} else
if ((--speed)<=-20)
if (!eventmanager.sendcom(EV_KILL,mv.id)) speed=-19;
}
ObjMover::ObjMover(int _objlinkID, int _angle, int _speed)
:Actor(0,0,F_TESCHIO,1,MVT_0) // F_TESCHIO = no one fig
{
Object *objlink;
object_type=OBJT_OBJMOVER;
/*
if ((objlink = objectslist.get(objlinkID = _objlinkID)) == NULL)
error("ObjMover","no Object");
*/
objlink = objectslist.get(objlinkID = _objlinkID);
if (_speed>24) speed=24; else speed=_speed;
mover->angle = _angle;
mover->x = objlink->mover->x;
mover->y = objlink->mover->y;
mover->z = objlink->mover->z;
mover->shdim = 3;
mover->flags = 0; // no visible, no hittable, nothing !
bounceang = 0;
}
ObjMover::ObjMover(int handle)
:Actor(handle) {
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&bounceang,sizeof(bounceang));
CRC_read(handle,&objlinkID,sizeof(objlinkID));
}
void ObjMover::save(int handle) {
Actor::save(handle);
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&bounceang,sizeof(bounceang));
CRC_write(handle,&objlinkID,sizeof(objlinkID));
}
void ObjMover::animate() {
Object *objlink = objectslist.get(objlinkID);
Mover &mv = *mover;
if (objlink==NULL) {
eventmanager.sendcom(EV_KILL,mv.id);
return;
}
if (speed>0) {
remove();
fixed nx = mv.x + (costab[mv.angle]*(speed>>1)),
ny = mv.y + (sintab[mv.angle]*(speed>>1));
if (!mv.canmove(nx,mv.y)) {
if (mv.angle<=ANG180) mv.angle=ANG180-mv.angle;
else mv.angle=ANG180+ANG360-mv.angle;
} else mv.x = nx;
if (!mv.canmove(mv.x,ny)) {
if (mv.angle!=ANG0) mv.angle=ANG360-mv.angle;
} else mv.y = ny;
bounceang = angleadd(bounceang,(12-(speed>>1))<<4);
objlink->mover->z = mover->z+LABS(fixmul(lshl16(speed<<1),sintab[bounceang]));
objlink->remove();
objlink->mover->x = mv.x;
objlink->mover->y = mv.y;
objlink->place();
place();
speed--;
} else {
objlink->mover->z = mv.z;
eventmanager.sendcom(EV_KILL,mv.id);
}
}
void ObjMover::handle_event(TEvent &event) {
Object::handle_event(event);
switch (event.what) {
case EV_KILL:
if (event.source == objlinkID) {
eventmanager.sendcom(EV_KILL,mover->id);
objlinkID = -1; // morte forzata !
}
}
}
Bonus::Bonus(fixed px, fixed py)
:LightActor(px,py,F_BONUS,1,2,3,MVT_0) {
object_type=OBJT_BONUS;
mover->z = 24l<<FIXSHIFT;
CLRFLAG(mover->flags,OMF_UNWALKABLE|OMF_HITABLE);
SETFLAG(oflags,OFL_TAKEABLE);
animtrig = random(16);
animang = random(ANG360);
lightz = mover->z;
}
Bonus::Bonus(int handle)
:LightActor(handle) {
animtrig = random(16);
animang = random(ANG360);
}
void Bonus::animate() {
if (++animtrig >= 16) {
animtrig = 0;
if (++animcount > 1) animcount = 0;
}
animang = angleadd(animang,ANGLVL<<2);
lightz = mover->z = (24l<<FIXSHIFT)+(sintab[animang]<<2);
}
int Bonus::getlightfig() {
return F_CIRCLIGHT;
}
AntiKaos::AntiKaos(fixed px, fixed py) // ...sembra un Bonus
:LightActor(px,py,F_ANTIKAOS,-16,1,3,MVT_0) {
object_type = OBJT_ANTIKAOS;
lightz = mover->z = 40l<<FIXSHIFT;
CLRFLAG(mover->flags,OMF_UNWALKABLE|OMF_HITABLE);
SETFLAG(oflags,OFL_TAKEABLE);
animtrig = random(ANG360);
animang = random(ANG360);
}
AntiKaos::AntiKaos(int handle)
:LightActor(handle) {
animtrig = random(ANG360 & 0x7ff8);
animang = random(ANG360 & 0x7ffc);
}
void AntiKaos::animate() {
if (Kaos_count == -1) {
eventmanager.sendcom(EV_KILL,mover->id);
eventmanager.sendcom(EV_MESSAGE,MSG_KAOS);
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(mover->x,mover->y,mover->z,
mover->angle,BOOM_SMOG));
play3Dsound(mover->x,mover->y,SND_MISSILE,SM_NORMVOL,SYSOWN,SFL_NORMAL);
} else {
mover->angle = animang = angleadd(animang,ANGLVL<<2);
lightz = mover->z = (40l<<FIXSHIFT)+(sintab[animang]<<1);
animtrig = angleadd(animtrig,ANGLVL<<3);
lightpow = 4+lshr16(sintab[animtrig]<<3);
}
}
int AntiKaos::getlightfig() {
return F_CIRCLIGHT;
}
void AntiKaos::handle_event(TEvent &event) {
//if (event.what != EV_GOT)
Object::handle_event(event);
switch (event.what) {
case EV_GOT: // c'era un modo pi— facile...
eventmanager.sendcom(EV_ANTIKAOS,mover->id);
break;
}
}
Enemy::Enemy(fixed px, fixed py, byte type)
:Actor(px,py,F_SPIDER,-8,MVT_2)
{
animtrig = 0;
walkspeed = 2;
speed = 0;
mover->shdim = 4; // ??? !!! serve ???
animstate = 2;
hitangle=0;
switch (type) {
case F_BUB:
changefig(F_BUB,-8);
mover->z = 32l<<16;
health = 80;
walkspeed = 1;
break;
case F_FACE:
changefig(F_FACE,-8);
mover->z = 32l<<16;
health = 20;
mover->shdim = 4;
break;
}
posneg = 1;
firstfig = figstart;
}
void Enemy::animate() {
if (viewstate) return;
switch (animstate) {
case 2: // Anim & Walk
if (++animtrig > 15) animtrig = 0;
animcount = animtrig >> 3;
case 0: // Walk
char dir = mover->angle/ANG45; //flags & 0x07,
if (!had_seen()) return;
remove();
if (!random(50)) dir = (dir+random(3)-1) & 0x7;
if (have_seen() && random(100)==37) {
switch (figstart) {
case F_BUB:
play3Dsound(0l,0l,SND_BUB,SM_NORMVOL,mover->id,SFL_AUTO);
break;
}
}
if (random(17)==13) posneg = -posneg;
for (int i=0;i<8;i++) {
if (mover->move(mover->angle,walkspeed)) i=8;
else {
dir=(dir+8+posneg) & 0x07;
mover->angle = (int)dir*ANG45;
}
}
place();
break;
case 1: // Back Walk or Die
if (health>0) {
if (speed) {
remove();
mover->fluidmove(hitangle,lshl16(speed--));
place();
} else {
animtrig=0;
animstate=2;
animcount=0;
changefig(firstfig,-8);
}
} else {
if (speed) {
remove();
mover->fluidmove(hitangle,lshl16(speed--));
place();
}
if (animtrig) {
mover->flags = OMF_VISIBLE;
if (!(--animtrig & 3)) animcount++;
} else if (!speed) {
selflight=0;
makeObject();
ownerdead(mover->id);
}
}
break;
}
}
void Enemy::handle_event(TEvent &event) {
int dead;
Object::handle_event(event);
if (health && (event.what == EV_HIT ||
(event.what == EV_SCODE && event.source == SC_MNStrg))) {
if (event.what == EV_SCODE) {
health=0; speed=0;
dead=1;
} else {
if ((health-=event.data.msg.y) <=0) {
health=0;
eventmanager.senddirect(EV_ADDSTAT,mover->id,event.source,
STT_KILL,1);
dead=1;
} else dead=0;
switch (figstart) {
case F_BUB:
if ((speed+=event.data.msg.y>>1) > 12) speed = 12;
break;
case F_FACE:
if ((speed+=event.data.msg.y<<1) > 18) speed = 18;
break;
}
hitangle=event.data.msg.x;
}
switch (firstfig) {
case F_FACE:
changefig(firstfig+10+(dead<<1),2-dead);
animtrig=19-(dead<<2);
break;
case F_BUB:
changefig(firstfig+12+(dead<<1),2-dead);
animtrig=23-(dead<<2);
break;
}
animcount=0;
animstate=1;
}
// eventmanager.sendcom(EV_KILL,mover->id);
}
Slimer::Slimer(fixed px, fixed py)
:Actor(px,py,F_SLIMER,-8,MVT_2) {
object_type=OBJT_SLIMER;
numenemies++; // !!!
animstate=2;
animtrig=0;
mover->z = 38l<<FIXSHIFT;
health = 28;
mover->shdim = 5;
scanangle = ANG0;
objlink = -1;
mysound = -1;
floatangle = ANG0;
cannoncharge = 0;
speed = 0;
posneg = 1;
sndcount = 0;
turning = 0; turnnum = 0; turnable=0;
}
Slimer::Slimer(int handle)
:Actor(handle) {
numenemies++; // !!!
CRC_read(handle,&animstate,sizeof(animstate));
CRC_read(handle,&animtrig,sizeof(animtrig));
CRC_read(handle,&posneg,sizeof(posneg));
CRC_read(handle,&objlink,sizeof(objlink));
CRC_read(handle,&scanangle,sizeof(scanangle));
CRC_read(handle,&cannoncharge,sizeof(cannoncharge));
CRC_read(handle,&turning,sizeof(turning));
CRC_read(handle,&turnnum,sizeof(turnnum));
CRC_read(handle,&turnable,sizeof(turnable));
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&hitangle,sizeof(hitangle));
sndcount=0; mysound=-1; floatangle=ANG0;
}
void Slimer::save(int handle) {
Actor::save(handle);
CRC_write(handle,&animstate,sizeof(animstate));
CRC_write(handle,&animtrig,sizeof(animtrig));
CRC_write(handle,&posneg,sizeof(posneg));
CRC_write(handle,&objlink,sizeof(objlink));
CRC_write(handle,&scanangle,sizeof(scanangle));
CRC_write(handle,&cannoncharge,sizeof(cannoncharge));
CRC_write(handle,&turning,sizeof(turning));
CRC_write(handle,&turnnum,sizeof(turnnum));
CRC_write(handle,&turnable,sizeof(turnable));
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&hitangle,sizeof(hitangle));
}
void Slimer::animate() {
fixed cx, cy, dist, alt;
Object *object;
int i,j;
char oldseen;
if (viewstate) return;
switch (animstate) {
case 0: // Walk & Scan
case 3: // Persecution
// Scanner
if (cannoncharge) cannoncharge--;
cx=mover->x; cy=mover->y;
i = fireray(cx,cy,scanangle,0,dist,alt,mover->id);
oldseen = objseen;
objseen = 0;
if (i>=0) {
switch ((object = objectslist.get(i))->figstart) {
case F_SLIMER:
// Se non Š un vecchio nemico allora niente...
if (objlink!=i) {
scanangle = angleadd(scanangle,ANG30>>1);
break;
}
case F_SPIDER:
// Se prima avevo sott'occhio un Player allora niente...
if (objlink>=0 && animstate==3 &&
objectslist.get(objlink)->get_type() == OBJT_PLAYER) {
scanangle = angleadd(scanangle,ANG30>>1);
break;
}
case F_PLAYER: // normale
case F_PLAYER+32: // colpito
objlink = i;
objseen = 1;
mover->angle = scanangle;
turnnum=0;turning=0;
if (dist >= 200l<<FIXSHIFT) { // Fire slime
if (!cannoncharge) {
animstate+=4;
animtrig=0;
} else
scanangle = anglesub(scanangle,ANG30>>1);
} else
if (dist <= 80l<<FIXSHIFT) { // Attacca
animstate+=5;
animtrig=0;
} else
scanangle = anglesub(scanangle,ANG30>>1);
break;
default: scanangle = angleadd(scanangle,ANG30>>1);
}
} else scanangle = angleadd(scanangle,ANG30>>1);
// Turner Reset
if (oldseen && !objseen) {
turnable=0;
turning=0;
turnnum=0;
posneg = !posneg;
//mover->angle = (mover->angle/(ANG45>>3))*(ANG45>>3);
}
// Move
remove();
if (objlink>=0) {
object = objectslist.get(objlink);
if (object!=NULL && ((Actor *)object)->health>0) {
if (objseen) {
// Se l'oggetto Š visibile, gli corro addosso...
for (i=3;i>=0;i--)
if ((j = mover->move(mover->angle,i))>0) break;
// ...e gli giro intorno
if (j<2) mover->move(anglesub(mover->angle,ANG60),1);
} else {
// Cammina un p• prima di poter girare di nuovo
if (turnable) {
//if (mover->move(mover->angle,1)) turnable--;
//else turnable=0;
mover->move(mover->angle,2);
turnable--;
// Si avvicina al muro
if (turnnum && turnable<5) {
if (posneg) mover->move(anglesub(mover->angle,ANG60),1);
else mover->move(angleadd(mover->angle,ANG60),1);
}
} else
if (turning) { // Cambia direzione
// Giro nella direzione posneg se turning>0
// altrimenti faccio il contrario
if (turning<0 ^ posneg)
mover->angle = angleadd(mover->angle,ANG45>>3);
else
mover->angle = anglesub(mover->angle,ANG45>>3);
if (!(mover->angle % ANG90)) {
turning=0;
//if (turnnum)
turnable=8;
}
mover->fluidmove(mover->angle,FIXONE>>1);
} else
if (turnnum) {
turnnum--; turning--;
/*
if (posneg) i = (anglesub(mover->angle,ANG90)/ANG90)*ANG90;
else i = (angleadd(mover->angle,ANG90)/ANG90)*ANG90;
*/
if (posneg) i = anglesub(mover->angle,ANG90);
else i = angleadd(mover->angle,ANG90);
for (j=0; j<3; j++) {
if (mover->move(i,2)<2) {
if (posneg) i = angleadd(i,ANG90);
else i = anglesub(i,ANG90);
turnnum++; turning++;
} else break;
}
if (turnnum>=16) {
turnnum=0;
posneg=!posneg;
}
} else {
int dx = (lshr16(object->mover->x - mover->x)) >> 4,
dy = (lshr16(object->mover->y - mover->y)) >> 4,
dir;
if (animstate==0 && ABS(dx)+ABS(dy)>32) objlink=-1;
if (dx>1) {
if (dy>0) dir=1; else
if (dy<0) dir=7; else
dir=0;
} else
if (dx<1) {
if (dy>0) dir=3; else
if (dy<0) dir=5; else
dir=4;
} else {
if (dy>0) dir=2; else
if (dy<0) dir=6; else
dir=-1;
}
if (dir>=0) {
mover->angle = dir*ANG45;
if (!mover->move(mover->angle,2)) {
turnnum++;
turning++;
}
} else objlink=-1;
}
}
} else objlink = -1;
} else {
//if (random(20)==13)
// if (posneg) mover->angle = anglesub(mover->angle,ANG45>>4);
// else mover->angle = angleadd(mover->angle,ANG45>>4);
animstate=0;
if (!mover->move(mover->angle,1)) {
if (posneg) mover->angle = anglesub(mover->angle,ANG45>>3);
else mover->angle = angleadd(mover->angle,ANG45>>3);
//mover->angle = (mover->angle/ANG45)*ANG45;
//for (i=0;i<8;i++) {
// if (mover->move(1)) break;
// mover->angle = angleadd(mover->angle,ANG45);
//}
}
}
place();
// Animate
if (++animtrig > 31) animtrig = 0;
animcount = animtrig >> 4;
// Fly & talk
if (!sndcount) {
if (mysound<0) {
if (objlink>=0) { // && nearPlayer(192l<<FIXSHIFT)) {
if (nearPlayer(192l<<FIXSHIFT)) {
mysound = play3Dsound(0l,0l,SND_SLIME2,SM_NORMVOL,mover->id,SFL_AUTO);
sndcount = 108;
}
} else
if (have_seen() || nearPlayer(140l<<FIXSHIFT)) {
mysound = play3Dsound(0l,0l,SND_SLIME1,SM_NORMVOL,mover->id,SFL_AUTO);
sndcount = 90;
reset();
}
}
} else sndcount--;
floatangle = angleadd(floatangle,ANGLVL<<3);
mover->z = (38l<<FIXSHIFT)+(sintab[floatangle]<<2);
break;
case 1:
if (speed) {
remove();
mover->fluidmove(hitangle,lshl16(speed--));
place();
} else {
if (health) {
animtrig=0;
animstate=3; // Persecution !!!
animcount=0;
changefig(F_SLIMER,-8);
} else
if (!animtrig) {
selflight=0;
makeObject();
eventmanager.sendcom(EV_DEAD,mover->id);
//ownerdead(mover->id); // !!! usare mysound ???
}
}
if (!health && animtrig) {
if (GETFLAG(mover->flags,OMF_UNWALKABLE)) {
mover->z = 38l<<FIXSHIFT;
remove();
mover->flags = OMF_VISIBLE;
place();
SETFLAG(oflags,OFL_TAKEABLE);
}
if (!(--animtrig & 3)) animcount++;
if (animtrig==4)
play3Dsound(mover->x,mover->y,SND_SLIMDOWN,SM_NORMVOL,
SYSOWN,SFL_NORMAL);
}
break;
case 4: // Fire
case 7:
switch (animtrig++) {
case 0: break;
case 6:
changefig(F_SLIMER+14,2);
animcount=0;
break;
case 12:
// re-scan
cx=mover->x; cy=mover->y;
fireray(cx,cy,scanangle,0,dist,alt,mover->id);
delete mm_reserve(sizeof(Fireball));
object = new Fireball(mover->x,mover->y,scanangle,F_SLIMFIRE,
mover->z,alt,dist,mover->id);
mysound = play3Dsound(mover->x,mover->y,SND_MISSILE,SM_NORMVOL,
mover->id,SFL_NORMAL);
objectslist.put(object);
//scanangle = anglesub(scanangle,ANG30>>1);
cannoncharge = 48;
break;
case 18:
changefig(F_SLIMER,-8);
animcount=0;
animtrig=0;
animstate-=4;
break;
}
break;
case 5: // Attack
case 8:
remove();mover->move(mover->angle,0);place();
switch (animtrig++) {
case 0: break;
case 6:
changefig(F_SLIMER+10,2);
animcount=0;
break;
case 12:
animcount=1;
mysound=play3Dsound(mover->x,mover->y,SND_SLIMATT,SM_NORMVOL,
mover->id,SFL_NORMAL);
break;
case 16:
// re-scan
cx=mover->x; cy=mover->y;
i = fireray(cx,cy,scanangle,0,dist,alt,mover->id);
if (i>=0 && dist<80l<<FIXSHIFT)
//object = objectslist.get(i);
eventmanager.senddirect(EV_HIT,mover->id,i,mover->angle,6);
//scanangle = anglesub(scanangle,ANG30>>1);
break;
case 20: changefig(F_SLIMER,-8); break;
case 21: animstate-=5; animtrig=0; break;
}
break;
case 2:
if (had_seen()) {
animstate=0;
reset(); // !!!!
}
break;
}
}
void Slimer::handle_event(TEvent &event) {
int dead;
Object::handle_event(event);
if (!health) return;
if ((event.what == EV_HIT || event.what == EV_POISON ||
(event.what == EV_SCODE && event.source == SC_MNStrg))) {
if (event.what == EV_SCODE) {
health=0; speed=0;
dead=1;
} else {
if (event.source != mover->id) objlink = event.source;
// Come fa a colpirsi da solo ?
// Con i barili o con un muro di fronte !
if ((health-=event.data.msg.y) <=0) {
health=0;
eventmanager.senddirect(EV_ADDSTAT,mover->id,event.source,
STT_KILL,1);
play3Dsound(mover->x,mover->y,SND_SLIMDEAD,SM_NORMVOL,
SYSOWN,SFL_NORMAL);
dead=1;
} else {
mysound=play3Dsound(0l,0l,SND_SLIMHIT,SM_NORMVOL,
mover->id,SFL_AUTO);
dead=0;
}
if ((speed += event.data.msg.y<<1) > 18) speed = 18;
hitangle=event.data.msg.x;
}
changefig(F_SLIMER+14+(dead<<1),2-dead);
animtrig=23-(dead<<2);
animcount=0;
animstate=1;
} else
if (mysound>=0 && event.what == EV_ENDSOUND && event.source==mysound)
mysound=-1;
}
Spider::Spider(fixed px, fixed py)
:Actor(px,py,F_SPIDER,-8,MVT_2) {
object_type=OBJT_SPIDER;
numenemies++; // !!!
animstate=2;
animtrig=0;
mover->z = 22l<<FIXSHIFT;
mover->shdim=5; // !!!!!
health = 10;
speed = 0;
hitangle=0;
scanangle = ANG0;
objlink = -1;
mysound=-1;
cannoncharge=0;
}
Spider::Spider(int handle)
:Actor(handle) {
numenemies++; // !!!
CRC_read(handle,&animstate,sizeof(animstate));
CRC_read(handle,&animtrig,sizeof(animtrig));
CRC_read(handle,&objlink,sizeof(objlink));
CRC_read(handle,&scanangle,sizeof(scanangle));
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&hitangle,sizeof(hitangle));
CRC_read(handle,&cannoncharge,sizeof(cannoncharge));
mysound=-1;
}
void Spider::save(int handle) {
Actor::save(handle);
CRC_write(handle,&animstate,sizeof(animstate));
CRC_write(handle,&animtrig,sizeof(animtrig));
CRC_write(handle,&objlink,sizeof(objlink));
CRC_write(handle,&scanangle,sizeof(scanangle));
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&hitangle,sizeof(hitangle));
CRC_write(handle,&cannoncharge,sizeof(cannoncharge));
}
void Spider::animate() {
fixed cx, cy, dist, alt;
Object *object;
int i;
if (viewstate) return;
switch (animstate) {
case 3: // Run out
case 0: // Walk & Scan
// Scanning
if (cannoncharge) cannoncharge--;
if (animtrig & 1) {
/*
if (ABS(scanangle-mover->angle)>ANG90)
scanangle = anglesub(mover->angle,ANG90);
*/
scanangle = angleadd(scanangle,ANG45>>1);
cx=mover->x; cy=mover->y;
i = fireray(cx,cy,scanangle,0,dist,alt,mover->id);
if (i>=0)
switch ((object = objectslist.get(i))->figstart) {
case F_SLIMER:
if (ABS(object->mover->angle-angleadd(scanangle,ANG180))<=ANG45) {
if (GETFLAG(gameflags,GFL_NORANDOM) || random(2))
mover->angle = angleadd(scanangle,ANG90);
else
mover->angle = anglesub(scanangle,ANG90);
animstate = 3;
objlink = i;
}
break;
case F_PLAYER:
case F_PLAYER+32:
animstate=0;
objlink = i;
mover->angle = scanangle;
if (dist >= 148l<<FIXSHIFT) {
if (!cannoncharge) {
animstate=4;
animtrig=0;
} else scanangle = anglesub(scanangle,ANG45>>1);
} else
if (dist <= 96l<<FIXSHIFT) {
animstate=5;
animtrig=0;
} else scanangle = anglesub(scanangle,ANG45>>1);
break;
}
}
remove();
if (objlink>=0) {
object = objectslist.get(objlink);
if (object != NULL || ((Actor *)object)->health<=0) {
if (mover->move(mover->angle,3)<2) {
//if (animstate==0) {
int dx = (lshr16(object->mover->x - mover->x)) >> 5,
dy = (lshr16(object->mover->y - mover->y)) >> 5;
if (ABS(dx)+ABS(dy)>6) objlink=-1;
//} else objlink=-1;
}
} else objlink = -1;
} else {
if (!GETFLAG(gameflags,GFL_NORANDOM)) {
if (random(20)==13)
if (random(2)) mover->angle = angleadd(mover->angle,ANG45);
else mover->angle = anglesub(mover->angle,ANG45);
}
if (mover->move(mover->angle,3)<2)
for (i=0;i<8;i++) {
if (mover->move(mover->angle,3)) break;
mover->angle = angleadd(mover->angle,ANG45);
}
}
place();
// Animate
if (++animtrig >= 8) animtrig = 0;
animcount = animtrig >> 2;
// Sound
if (/*!animstate &&*/ mysound<0 && nearPlayer(160l<<FIXSHIFT))
mysound=play3Dsound(0l,0l,SND_SPIDNEAR,SM_NORMVOL,mover->id,SFL_AUTO);
break;
case 1:
if (speed) {
remove();
mover->fluidmove(hitangle,lshl16(speed--));
place();
} else {
if (health) {
animtrig=0;
animstate=0;
animcount=0;
changefig(F_SPIDER,-8);
} else if (!animtrig) {
selflight=0;
makeObject();
eventmanager.sendcom(EV_DEAD,mover->id);
// ownerdead(mover->id); // ??? !!!!
}
}
if (!health && animtrig) {
if (GETFLAG(mover->flags,OMF_UNWALKABLE)) {
remove();
mover->flags = OMF_VISIBLE;
place();
SETFLAG(oflags,OFL_TAKEABLE);
}
if (!(--animtrig & 3)) animcount++;
if (animtrig==4)
play3Dsound(mover->x,mover->y,SND_SPIDDOWN,SM_NORMVOL,
SYSOWN,SFL_NORMAL);
}
break;
case 4: // Dispel Venom
switch (animtrig++) {
case 0: break;
case 6:
changefig(F_SPIDER+10,2);
animcount=0;
break;
case 12:
// re-scan
cx=mover->x; cy=mover->y;
fireray(cx,cy,scanangle,0,dist,alt,mover->id);
delete mm_reserve(sizeof(Fireball));
object = new Fireball(mover->x,mover->y,scanangle,/*0,*/F_SPIDFIRE,
mover->z,alt,dist,mover->id);
play3Dsound(mover->x,mover->y,SND_MISSILE,SM_NORMVOL,
mover->id,SFL_NORMAL);
objectslist.put(object);
scanangle = anglesub(scanangle,ANG45>>1);
cannoncharge = 40;
break;
case 16: changefig(F_SPIDER,-8);
animcount=0; break;
case 20: animtrig=0; animstate=0; break;
}
break;
case 5: // Attack
remove();mover->move(mover->angle,0);place();
switch (animtrig++) {
case 0: break;
case 6:
changefig(F_SPIDER+12,2);
animcount=0;
play3Dsound(mover->x,mover->y,SND_SPIDATT,SM_NORMVOL,
mover->id,SFL_NORMAL);
break;
case 12:
// re-scan
cx=mover->x; cy=mover->y;
i = fireray(cx,cy,scanangle,0,dist,alt,mover->id);
scanangle = anglesub(scanangle,ANG45>>1);
if (i>=0)
eventmanager.senddirect(EV_HIT,mover->id,i,scanangle,4);
break;
case 18: changefig(F_SPIDER,-8);
animcount=0; break;
case 20: animtrig=0; animstate=0; break;
}
break;
case 2:
if (had_seen()) {
animstate=0;
reset(); // !!!!
}
break;
}
}
void Spider::handle_event(TEvent &event) {
int dead;
Object::handle_event(event);
if (!health) return;
if ((event.what == EV_HIT ||
(event.what == EV_SCODE && event.source == SC_MNStrg))) {
if (event.what == EV_SCODE) {
health=0; speed=0;
dead=1;
} else {
if (event.source != mover->id) {
animstate = 3;
objlink = event.source;
mover->angle = angleadd(event.data.msg.x,ANG90);
}
if ((health-=event.data.msg.y) <=0) {
health=0;
eventmanager.senddirect(EV_ADDSTAT,mover->id,event.source,
STT_KILL,1);
play3Dsound(mover->x,mover->y,SND_SPIDDEAD,SM_NORMVOL,
SYSOWN,SFL_NORMAL);
dead=1;
} else {
mysound = play3Dsound(0l,0l,SND_SPIDHIT,SM_NORMVOL,
mover->id,SFL_AUTO);
dead=0;
}
if ((speed += event.data.msg.y*3>>1) > 16) speed = 16;
hitangle=event.data.msg.x;
}
changefig(F_SPIDER+12+(dead<<1),2-dead);
animtrig=19-(dead<<2);
animcount=0;
animstate=1;
} else
if (event.source==mysound && event.what == EV_ENDSOUND && mysound>=0)
mysound=-1;
}
Soldier::Soldier(fixed px, fixed py)
:Actor(px,py,F_SOLDIER,8,MVT_2) {
object_type=OBJT_SOLDIER;
numenemies++; // !!!
animstate=2;
animtrig=0;
mover->z = 40l<<16;
mover->shdim = 4;
health = 100;
speed = 0;
hitangle=0;
scanangle=ANG0;
zigzagang=ANG0;
recover=0;
objseen=0;
objlink=-1;
turncount=0;
havetoturn=0;
}
Soldier::Soldier(int handle)
:Actor(handle) {
numenemies++; // !!!
CRC_read(handle,&animstate,sizeof(animstate));
CRC_read(handle,&animtrig,sizeof(animtrig));
CRC_read(handle,&objlink,sizeof(objlink));
CRC_read(handle,&scanangle,sizeof(scanangle));
CRC_read(handle,&zigzagang,sizeof(zigzagang));
CRC_read(handle,&recover,sizeof(recover));
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&hitangle,sizeof(hitangle));
CRC_read(handle,&turncount,sizeof(turncount));
CRC_read(handle,&havetoturn,sizeof(havetoturn));
CRC_read(handle,&oldobjx,sizeof(oldobjx));
CRC_read(handle,&oldobjy,sizeof(oldobjy));
}
void Soldier::save(int handle) {
Actor::save(handle);
CRC_write(handle,&animstate,sizeof(animstate));
CRC_write(handle,&animtrig,sizeof(animtrig));
CRC_write(handle,&objlink,sizeof(objlink));
CRC_write(handle,&scanangle,sizeof(scanangle));
CRC_write(handle,&zigzagang,sizeof(zigzagang));
CRC_write(handle,&recover,sizeof(recover));
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&hitangle,sizeof(hitangle));
CRC_write(handle,&turncount,sizeof(turncount));
CRC_write(handle,&havetoturn,sizeof(havetoturn));
CRC_write(handle,&oldobjx,sizeof(oldobjx));
CRC_write(handle,&oldobjy,sizeof(oldobjy));
}
void Soldier::animate() {
fixed cx,cy,dist,alt;
int i,app;
Object *object;
if (viewstate) return;
if (health<100 && ++recover>=18) { health++; recover=0; }
switch (animstate) {
case 0:
case 3: // fuga dal missile
//case 5: // fuga ricostituente ELIMINATO
// Gestione animazione e suono del passo
if (++animtrig > 63) animtrig = 0;
if (!(animtrig & 0x000f)) {
switch(animtrig>>4) {
case 0: animcount=1; break;
case 1:
case 3: animcount=0;
if (nearPlayer(384l<<FIXSHIFT))
play3Dsound(mover->x,mover->y,SND_PASSO2,SM_NORMVOL,mover->id,SFL_NORMAL);
break;
case 2: animcount=2; break;
}
}
// Scanner (solo se non sta fuggendo dal missile)
if (animstate != 3) {
scanangle = angleadd(scanangle,ANG45>>1);
cx = mover->x; cy = mover->y;
i = fireray(cx,cy,scanangle,0,dist,alt,mover->id);
objseen = 0; // Nessun oggetto selezionato
if (i>=0) { // Visto un oggetto
object = objectslist.get(i);
if (i == objlink ||
(object->figstart >= F_PLAYER &&
object->figstart <= F_PLAYER+32)) {
// Se Š una vecchia conoscenza o un Player vivo
objlink = i; // Nuova conoscenza
oldobjx = object->mover->x;
oldobjy = object->mover->y;
objseen = 1;
mover->angle = scanangle; // Si dirige verso il nemico
if (dist<70l<<FIXSHIFT) { // E' a tiro di spada
animstate=4; // Attack
animtrig=0;
} else {
// preparo la mira in caso la prossima volta
// Š pi— vicino
scanangle = anglesub(scanangle,ANG45>>1);
}
}
}
}
// Movimento
remove();
if (animstate == 3) { // Fuggire via
if (mover->move(mover->angle,2)<2) { // ostacolo
animstate=0; // smetti di fuggire
turncount=0;
havetoturn=0;
}
} else {
if (objlink>=0) { // c'era qualcuno che mi stava antipatico...
object = objectslist.get(objlink);
if (object != NULL && ((Actor *)object)->health>0) {
// Il tizio Š ancora vivo
if (!objseen) { // non lo vede
// Inseguimento guidato (circolare)
if (turncount) {
if (turncount>0) {
mover->angle = anglesub(mover->angle,ANG45>>3);
if (!(--turncount)) havetoturn--;
} else
if (turncount<0) {
mover->angle = angleadd(mover->angle,ANG45>>3);
if (!(++turncount)) havetoturn++;
}
//mover->move(mover->angle,0);
} else
if (havetoturn) {
if (mover->move(app = anglesub(mover->angle,ANG45),2)>1) {
turncount = 8;
} else {
int j;
j = xytoidx(mover->x+(costab[app]<<6),
mover->y+(sintab[app]<<6));
if ((Map[j].type==MTP_DOOR1 || Map[j].type==MTP_DOOR2) &&
(app = doormanager.doorpos(Map[j].data))<64) {
eventmanager.sendshort(EV_ACTIVATE,mover->id,0,j,0);
mover->move(mover->angle,0);
} else {
//mover->angle = angleadd(mover->angle,ANG45);
if (mover->move(mover->angle,2)<2) {
j = xytoidx(mover->x+(costab[mover->angle]<<6),
mover->y+(sintab[mover->angle]<<6));
if (Map[j].type==MTP_DOOR1 || Map[j].type==MTP_DOOR2) {
if (!(app = doormanager.doorpos(Map[j].data)))
eventmanager.sendshort(EV_ACTIVATE,mover->id,0,j,0);
else
if (app == 64) turncount = -8;
} else
turncount = -8;
}
}
}
} else {
int dx = (lshr16(oldobjx - mover->x)) >> 4,
dy = (lshr16(oldobjy - mover->y)) >> 4,
dir;
if (dx>0) {
if (dy>0) dir=1; else
if (dy<0) dir=7; else
dir=0;
} else
if (dx<0) {
if (dy>0) dir=3; else
if (dy<0) dir=5; else
dir=4;
} else {
if (dy>0) dir=2; else
if (dy<0) dir=6; else
dir=-1; // niente... aspetto un indizio
}
if (dir>=0)
mover->angle = dir*ANG45;
if (!mover->move(mover->angle,2)) {
int j = xytoidx(mover->x+(costab[mover->angle]<<6),
mover->y+(sintab[mover->angle]<<6));
if (Map[j].type==MTP_DOOR1 || Map[j].type==MTP_DOOR2)
eventmanager.sendshort(EV_ACTIVATE,mover->id,0,j,0);
else
turncount = -16;
}
}
} else {
turncount=0;
havetoturn=0;
// Guida a zig-zag
zigzagang=angleadd(zigzagang,ANGLVL<<3);
i = mover->angle;
if ((mover->angle = i+(int)fixmul(ANG45,sintab[zigzagang]))>=ANG360)
mover->angle-=ANG360; else
if (mover->angle<ANG0) mover->angle+=ANG360;
if (!mover->move(mover->angle,3)) {
int j = xytoidx(mover->x+(costab[mover->angle]<<6),
mover->y+(sintab[mover->angle]<<6));
if (Map[j].type==MTP_DOOR1 || Map[j].type==MTP_DOOR2)
eventmanager.sendshort(EV_ACTIVATE,mover->id,0,j,0);
}
mover->angle = i;
}
} else {
//mover->angle = angleadd(mover->angle,ANG180);
objlink=-1;
turncount=0;
havetoturn=0;
}
} else {
if (!mover->move(mover->angle,1)) {
mover->angle = (mover->angle/ANG45)*ANG45;
mover->angle = angleadd(mover->angle,ANG45);
}
}
}
place();
break;
case 1: // Colpito
recover=0;
if (speed) {
remove();
mover->fluidmove(hitangle,lshl16(speed--));
if (speed) speed--;
place();
} else {
if (health) {
animtrig=0;
animstate=0;
animcount=0;
turncount=0;
havetoturn=0;
changefig(F_SOLDIER,8);
} else if (!animtrig) {
selflight=0;
makeObject();
eventmanager.sendcom(EV_DEAD,mover->id);
//ownerdead(mover->id);
}
}
if (!health && animtrig) {
if (GETFLAG(mover->flags,OMF_UNWALKABLE)) {
remove();
mover->flags = OMF_VISIBLE;
place();
SETFLAG(oflags,OFL_TAKEABLE);
}
if (!(--animtrig % 6)) animcount++;
if (animtrig==6)
play3Dsound(mover->x,mover->y,SND_SOLDDOWN,SM_NORMVOL,
SYSOWN,SFL_NORMAL);
}
break;
case 4: // Attack
if (animtrig & 1) {remove(); mover->move(mover->angle,0); place();}
switch (animtrig++) {
case 0: animcount=0; break;
case 3:
changefig(F_SOLDIER+24,2);
//animcount=0;
play3Dsound(mover->x,mover->y,SND_SOLDATT,SM_NORMVOL,
mover->id,SFL_NORMAL);
break;
case 8: animcount++; break;
case 9:
// re-scan
cx=mover->x; cy=mover->y;
i = fireray(cx,cy,scanangle,0,dist,alt,mover->id);
if (i>=0 && dist<80l<<FIXSHIFT)
eventmanager.senddirect(EV_HIT,mover->id,i,scanangle,12);
break;
case 14:
changefig(F_SOLDIER,8);
animcount=0; break;
case 16:
animtrig=0;
animstate=0;
turncount=0;
havetoturn=0;
break;
}
break;
case 2:
if (had_seen()) {
animstate=0;
turncount=0;
havetoturn=0;
reset(); // !!!!
}
break;
}
}
void Soldier::handle_event(TEvent &event) {
int dead;
Object::handle_event(event);
if (!health) return;
if (event.what == EV_ALERT) {
animstate=3; // Let's run out !
if (anglesub(angleadd(mover->angle,ANG180),event.data.msg.x) <= ANG180)
mover->angle = anglesub(event.data.msg.x,ANG90);
else
mover->angle = angleadd(event.data.msg.x,ANG90);
} else
if ((event.what == EV_HIT ||
(event.what == EV_SCODE && event.source == SC_MNStrg))) {
if (event.what == EV_SCODE) {
health=0; speed=0;
dead=1;
} else {
if ((health-=event.data.msg.y) <=0) {
health=0;
eventmanager.senddirect(EV_ADDSTAT,mover->id,event.source,
STT_KILL,1);
play3Dsound(mover->x,mover->y,SND_SOLDDEAD,SM_NORMVOL,
SYSOWN,SFL_NORMAL);
dead=1;
} else {
play3Dsound(0l,0l,SND_SOLDHIT,SM_NORMVOL,
mover->id,SFL_AUTO);
dead=0;
}
if ((speed+=event.data.msg.y*3>>1) > 16) speed = 16;
scanangle = angleadd(hitangle=event.data.msg.x,ANG180);
objlink = event.source;
}
changefig(F_SOLDIER+28+(dead<<1),2-dead);
//animtrig=19-(dead<<2);
animtrig=29-(dead*6);
animcount=0;
animstate=1;
} else
if (event.what==EV_PLNOISE && event.source==objlink) {
//if (fixdist(event.data.pos.x-mover->x,event.data.pos.y-mover->y)<(640l<<FIXSHIFT)) {
oldobjx = event.data.pos.x;
oldobjy = event.data.pos.y;
//}
}
}
Mouse::Mouse(fixed px, fixed py)
:Actor(px,py,F_MOUSE,-8,MVT_2) {
object_type=OBJT_MOUSE;
animstate = 2;
health = 5;
mover->z = 4l<<16;
mover->shdim = 3;
CLRFLAG(mover->flags,OMF_UNWALKABLE);
}
Mouse::Mouse(int handle)
:Actor(handle) {
CRC_read(handle,&animstate,sizeof(animstate));
CRC_read(handle,&animtrig,sizeof(animtrig));
}
void Mouse::save(int handle) {
Actor::save(handle);
CRC_write(handle,&animstate,sizeof(animstate));
CRC_write(handle,&animtrig,sizeof(animtrig));
}
void Mouse::animate() {
if (viewstate) return;
switch (animstate) {
case 1: // dead
if (++animtrig>=20) {
remove();
mover->flags = OMF_VISIBLE;
place();
makeObject();
eventmanager.sendcom(EV_DEAD,mover->id);
//ownerdead(mover->id);
break;
}
animcount=animtrig>>2;
case 0: // forward
case 3: // backward
remove();
if (mover->move(mover->angle,2) != 2) {
if (!GETFLAG(gameflags,GFL_NORANDOM)) { // !!!
if (animstate!=1 && random(10)==5)
if (animstate) animstate=0; else animstate=3;
}
if (animstate) mover->angle = anglesub(mover->angle,ANG45);
else mover->angle = angleadd(mover->angle,ANG45);
}
place();
if (have_seen() && random(50)==37) {
play3Dsound(0l,0l,SND_TOPO,SM_NORMVOL,mover->id,SFL_AUTO);
reset(); // !!!!
}
break;
case 2:
if (had_seen()) {
animstate=0;
reset(); // !!!!
}
break;
}
}
void Mouse::handle_event(TEvent &event) {
/*
if (event.what == EV_GOT) {
health=0;
animtrig=17;
animstate=1;
changefig(F_MOUSE+8,1);
} else
*/
if (!health) return;
Object::handle_event(event);
if (event.what == EV_HIT ||
(event.what == EV_SCODE && event.source == SC_MNStrg)) {
if (event.what == EV_SCODE || (health-=event.data.msg.y) <= 0) {
health=0;
animtrig=0;
animstate=1;
changefig(F_MOUSE+5,1);
/*
if (event.what != EV_SCODE)
eventmanager.senddirect(EV_ADDSTAT,mover->id,event.source,
STT_KILL,1,0);
*/
}
}
}
FireBoom::FireBoom(fixed px, fixed py, fixed h, int angle, byte boomtype)
:LightActor(px,py,F_FIREBOOM,1,0,10,MVT_0) {
object_type=OBJT_FIREBOOM;
lightz = mover->z = h;
animtrig = 0; //animcount=0;
mover->flags = OMF_VISIBLE;
switch (type = boomtype) { // !
case BOOM_ASCIA: animcount++;
case BOOM_PALLOT: mover->shdim=2; break;
case BOOM_SPIDER: animcount+=3; selflight=2;
case BOOM_SLIMER: lightrange-=3; animcount+=6;
//case BOOM_3: animcount++;
case BOOM_MISSIL:
mover->shdim=4;
changefig(F_BOOM,1);
lightrange+=3;
break;
case BOOM_BLOOD:
decay = 0l;
/*
if (norandom) {
decayspd = FIXONE<<2;
animtrig = 0;
} else {
*/
decayspd = (16384l * (random(8)+1)) >> 3; // !!!
animtrig=random(4);
//}
mover->shdim=3;
animcount=0;
selflight=0;
changefig(F_BLOOD,1);
break;
case BOOM_SMOG:
changefig(F_SMOG,1);
//SETFLAG(oflags,OFL_ISLIGHT);
selflight=0;
//lightpow=0;
lightrange=0;
break;
default: type = BOOM_PALLOT;
}
mover->x -= costab[angle]<<(mover->shdim-1);
mover->y -= sintab[angle]<<(mover->shdim-1);
if (type != BOOM_MISSIL) CLRFLAG(oflags,OFL_HASLIGHT);
}
FireBoom::FireBoom(int handle)
:LightActor(handle) {
CRC_read(handle,&animtrig,sizeof(animtrig));
CRC_read(handle,&type,sizeof(type));
}
void FireBoom::save(int handle) {
LightActor::save(handle);
CRC_write(handle,&animtrig,sizeof(animtrig));
CRC_write(handle,&type,sizeof(type));
}
void FireBoom::animate() {
const byte light[6] = {2,4,5,3,2,1};
switch(type) {
case BOOM_PALLOT:
mover->z+=FIXONE>>1;
break;
case BOOM_BLOOD:
if ((mover->z-=decay)<FIXONE) mover->z=FIXONE;
decay += decayspd;
break;
case BOOM_SMOG:
mover->z+=FIXONE>>1;
//lightpow = 6-ABS((animcount*4+animtrig)-6);
break;
}
if (++animtrig >= 4) {
animtrig = 0;
animcount++;
switch (type) {
case BOOM_PALLOT:
if (animcount==2 && mover->under<0 /*&& mover->z==32l<<FIXSHIFT*/)
play3Dsound(mover->x,mover->y,SND_PROIETTILE,SM_NORMVOL,
SYSOWN,SFL_NORMAL & ~SFL_AUTOSTOP);
case BOOM_ASCIA:
if (animcount<=3) return;
animcount=3;
break;
case BOOM_MISSIL:
//case BOOM_3:
// animtrig++;
if (animcount<=4) {
remove();
lightrange = light[animcount];
place();
return;
}
animcount=4;
break;
case BOOM_BLOOD:
if (animcount<=4) return;
animcount=4;
eventmanager.sendshort(EV_CHGTEXTURE,2,0,mover->index,0);
break;
case BOOM_SMOG:
if (animcount<=2) return;
animcount=2;
break;
/*
case BOOM_4:
// animtrig++;
if (animcount==1) animcount++; else
if (animcount==3) animcount+=2; else
if (animcount==6) {animcount=5;break;}
remove();
lightrange = light[animcount];
place();
return;
*/
case BOOM_SLIMER:
// animtrig++;
if (animcount<=8) return;
animcount=8;
break;
case BOOM_SPIDER:
// animtrig++;
if (animcount<=11) return;
animcount=11;
break;
}
if (!eventmanager.sendcom(EV_KILL,mover->id)) {
animtrig=4;
animcount--;
}
}
}
int FireBoom::getlightfig() {
//if (type == BOOM_MISSILE)
return F_SPIKELIGHT;
//return -1;
}
Fireball::Fireball(fixed px, fixed py, int fireangle, /*int _vangle,*/ int type,
fixed h1, fixed h2, fixed dist, int _ownerid)
:LightActor(px,py,F_MISSILE,-8,3,5,MVT_1) // !!!
{
object_type=OBJT_FIREBALL;
mover->angle = fireangle;
mover->shdim = 3;
animtrig=0;
/*vangle = _vangle;*/
switch (type) {
case F_MISSILE:
shspeed = 4;
//animtrig = 2;
CLRFLAG(oflags,OFL_HASLIGHT);
break;
case F_SLIMFIRE:
changefig(F_SLIMFIRE,1);
shspeed = 3;
break;
case F_SPIDFIRE:
changefig(F_SPIDFIRE,1);
shspeed = 3;
CLRFLAG(oflags,OFL_HASLIGHT);
break;
}
if (dist>>=16+shspeed) deh = fixdiv(h2-h1,dist);
else deh = 0l;
lightz = mover->z = h1;
ownerid = _ownerid;
sendsound=1;
boomcount=1365; // CioŠ un bel p•
}
Fireball::Fireball(int handle)
:LightActor(handle) {
CRC_read(handle,&ownerid,sizeof(ownerid));
CRC_read(handle,&deh,sizeof(deh));
CRC_read(handle,&boomcount,sizeof(boomcount));
CRC_read(handle,&shspeed,sizeof(shspeed)); // !!! ...vabbŠ va
sendsound=1;
}
void Fireball::save(int handle) {
LightActor::save(handle);
CRC_write(handle,&ownerid,sizeof(ownerid));
CRC_write(handle,&deh,sizeof(deh));
CRC_write(handle,&boomcount,sizeof(boomcount));
CRC_write(handle,&shspeed,sizeof(shspeed)); // !!! ...vabbŠ va
}
void Fireball::animate() {
fixed &x = mover->x,
&y = mover->y,
&z = mover->z;
fixed cn, sn, cl, sl;
fixed cx,cy,dist,alt;
int idx, objid, altok;
int i;
Object *owner;
Mover *mvr;
if (viewstate) {
sendsound=1;
return;
}
if (sendsound) {
if (figstart==F_MISSILE) i=SM_MAXVOL; else i=SM_NORMVOL;
play3Dsound(0l,0l,SND_MISSILGO,i,mover->id,SFL_AUTO|SFL_CONTINUE);
sendsound=0;
}
switch (figstart) {
case F_MISSILE:
if (animtrig++ >= 3) {
animtrig=0;
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(mover->x,mover->y,mover->z,
mover->angle,BOOM_SMOG));
}
break;
case F_SLIMFIRE:
if (++animtrig>7) {
animcount = (animcount+1) & 1;
animtrig = 0;
}
break;
case F_SPIDFIRE:
deh-=256l;
if (++animtrig>4) {
animcount = (animcount+1) & 3;
animtrig = 0;
}
break;
}
remove();
if ((owner = objectslist.get(ownerid)) != NULL) {
// removes the owner !!!!!
owner->remove();
}
cn = costab[mover->angle];
sn = sintab[mover->angle];
/*
xl = sn<<mover->shdim;
yl = cn<<mover->shdim;
cn <<= shspeed;
sn <<= shspeed;
*/
objid = -1;
if (health) {
int old = boomcount;
/*
for (i=8;i>0;i--)
if (!mover->canmove(mover->x+cn/i,mover->y+sn/i)) break;
*/
cx=x-(sn<<mover->shdim); cy=y+(cn<<mover->shdim);
objid = fireray(cx,cy,mover->angle,0,dist,alt,mover->id);
if (objid==-2) boomcount=old=0; else {
altok = (objid<0) || (LABS(z-alt)<=FIXONE<<mover->shdim);
if (!(i = (dist<=64l<<FIXSHIFT && altok))) {
cx=x+(sn<<mover->shdim); cy=y-(cn<<mover->shdim);
objid = fireray(cx,cy,mover->angle,0,dist,alt,mover->id);
if (objid==-2) boomcount=old=0; else {
altok = (objid<0) || (LABS(z-alt)<=FIXONE<<mover->shdim);
if (!(i= (dist<=64l<<FIXSHIFT && altok))) {
cx=x; cy=y;
objid = fireray(cx,cy,mover->angle,0,dist,alt,mover->id);
if (objid==-2) boomcount=old=0; else {
altok = (objid<0) || (LABS(z-alt)<=FIXONE<<mover->shdim);
i = (dist<=64l<<FIXSHIFT && altok);
}
}
}
}
}
if (i)
if ((boomcount=(lshr16(dist)>>(shspeed/*+1*/)))<0 || boomcount>old)
boomcount = old;
if (objid>=0 && objectslist.get(objid)->figstart==F_SOLDIER)
eventmanager.senddirect(EV_ALERT,mover->id,objid,mover->angle,0);
} else {
i=1;
boomcount=0;
}
if (boomcount && (z+deh>FIXONE<<mover->shdim) &&
(z+deh<(128l<<FIXSHIFT)-(FIXONE<<mover->shdim))) {
// !!!!!!! occhio al 128 !!!!!!!!
boomcount--;
x += cn<<shspeed;
y += sn<<shspeed;
lightz = (z += deh);
} else {
//if (owner) i = ownerid; else i = mover->id;
/*
//idx = xytoidx(x---+cn,y----+sn);
objid = IDMap[idx];
while (objid) {
mvr = (objectslist.get(--objid))->mover;
if (mvr->flags & OMF_HITABLE)
// Sends an owner's message
if (figstart==F_SLIMFIRE)
eventmanager.senddirect(EV_HIT,i,objid,mover->angle,10);
else
eventmanager.senddirect(EV_HIT,i,objid,mover->angle,ArmList[ARM_FIREBALL].danno);
objid = mvr->underq(idx);
}
*/
cx=x; cy=y;
objid = fireray(cx,cy,mover->angle,0,dist,alt,mover->id);
altok = (objid<0) || (LABS(z-alt)<=FIXONE<<mover->shdim);
if (objid==-2 || (dist<64l<<FIXSHIFT && altok)) {
if (objid>=0) {
// Sends an owner's message
switch (figstart) {
case F_SLIMFIRE:
eventmanager.senddirect(EV_HIT,ownerid,objid,mover->angle,10);
break;
case F_SPIDFIRE:
eventmanager.senddirect(EV_POISON,ownerid,objid,mover->angle,6);
break;
default:
eventmanager.senddirect(EV_HIT,ownerid,objid,mover->angle,ArmList[ARM_BAZOOKA].power);
}
}
}
if (eventmanager.sendcom(EV_KILL,mover->id) && objid>-2) {
//ownerdead(mover->id);
// prima muoio e poi faccio il botto !
switch (figstart) {
case F_SPIDFIRE:
play3Dsound(x,y,SND_VENOM,SM_NORMVOL,SYSOWN,SFL_NORMAL);
i=BOOM_SPIDER;
break;
case F_SLIMFIRE:
eventmanager.sendpos(EV_BOOM,ownerid,x,y,8l); // !!!
i=BOOM_SLIMER;
//quake = 7;
break;
default:
eventmanager.sendpos(EV_BOOM,ownerid,x,y,(long)ArmList[ARM_BAZOOKA].power);
i=BOOM_MISSIL;
quake = 14;
break;
}
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(x,y,z,mover->angle,i));
}
}
if (owner) owner->place();
place();
}
void Fireball::handle_event(TEvent &event) {
if (!health) return;
Object::handle_event(event);
if (event.what == EV_HIT && event.data.msg.y>=10) health=0;
}
int Fireball::getlightfig() {
return F_CIRCLIGHT;
}
Bomb::Bomb(fixed px, fixed py, fixed h, int angle, int strng, int _ownerid)
:Actor(px,py,F_BOMB,-8) {
object_type = OBJT_BOMB;
if (!(strenght = strng)) makeObject(); // !!!
mover->z = h;
mover->angle = angle;
mover->shdim = 3; // inutile ?
timer = 5*36;
mover->flags = OMF_VISIBLE|OMF_HITABLE;
SETFLAG(oflags,OFL_TAKEABLE);
animtrig = 0;
decay = FIXONE;
ownerid = _ownerid;
}
Bomb::Bomb(int handle)
:Actor(handle) {
CRC_read(handle,&ownerid,sizeof(ownerid));
CRC_read(handle,&decay,sizeof(decay));
CRC_read(handle,&strenght,sizeof(strenght));
CRC_read(handle,&timer,sizeof(timer));
CRC_read(handle,&animtrig,sizeof(animtrig));
}
void Bomb::save(int handle) {
Actor::save(handle);
CRC_write(handle,&ownerid,sizeof(ownerid));
CRC_write(handle,&decay,sizeof(decay));
CRC_write(handle,&strenght,sizeof(strenght));
CRC_write(handle,&timer,sizeof(timer));
CRC_write(handle,&animtrig,sizeof(animtrig));
}
void Bomb::animate() {
//int i;
if (viewstate) return;
if (!timer--) {
//if (objectslist.get(ownerid)) i = ownerid; else i = mover->id;
eventmanager.sendcom(EV_KILL,mover->id);
eventmanager.sendpos(EV_BOOM,ownerid,mover->x,mover->y,
ArmList[ARM_BOMB].power);
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(mover->x,mover->y,mover->z+(8l<<16),
mover->angle,BOOM_MISSIL));
quake = 21; // !!!!!!!!!
} else {
if (animtrig>=0) {
if (++animtrig >= 6) {
animtrig = 0;
animcount = (animcount+1) % 3;
}
mover->z += (decay -= FIXONE>>2); // !!! ...forse ho esagerato
if (mover->z <= 0) {
mover->z = 0;
decay = -(decay>>1);
if (decay < (FIXONE>>4)) animtrig = -1;
strenght >>= 1;
play3Dsound(mover->x,mover->y,SND_BBOUNCE,SM_NORMVOL,mover->id,SFL_NORMAL);
}
if (strenght) {
Object *obj = objectslist.get(ownerid);
remove();
if (obj) obj->remove();
fixed nx = mover->x + (costab[mover->angle]*(strenght>>1)),
ny = mover->y + (sintab[mover->angle]*(strenght>>1));
if (!mover->canmove(nx,mover->y)) {
if (mover->angle<=ANG180) mover->angle=ANG180-mover->angle;
else mover->angle=ANG180+ANG360-mover->angle;
play3Dsound(mover->x,mover->y,SND_BBOUNCE,SM_NORMVOL,mover->id,SFL_NORMAL);
} else mover->x = nx;
if (!mover->canmove(mover->x,ny)) {
if (mover->angle!=ANG0) mover->angle=ANG360-mover->angle;
play3Dsound(mover->x,mover->y,SND_BBOUNCE,SM_NORMVOL,mover->id,SFL_NORMAL);
} else mover->y = ny;
if (obj) obj->place();
place();
//strenght--;
}
}
}
}
void Bomb::handle_event(TEvent &event) {
if (event.what == EV_GOT) {
if (!GETFLAG(oflags,OFL_ISACTOR)) {
Object::handle_event(event);
return;
}
} else Object::handle_event(event);
switch (event.what) {
case EV_HIT:
case EV_GOT:
//int i;
//if (objectslist.get(ownerid)) i = ownerid; else i = mover->id;
CLRFLAG(oflags,OFL_TAKEABLE);
eventmanager.sendcom(EV_KILL,mover->id);
eventmanager.sendpos(EV_BOOM,ownerid,mover->x,mover->y,
ArmList[ARM_BOMB].power);
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(mover->x,mover->y,mover->z+(8l<<16),
mover->angle,BOOM_MISSIL));
quake = 21; // !!!!!!!!!
break;
}
}
Torcia::Torcia(fixed px, fixed py, int fig)
:LightActor(px,py,fig,1,2,4,MVT_0)
{
object_type=OBJT_TORCIA;
if (fig==F_BRAZIER) {
mover->z = 20l<<16;
mover->shdim = 4;
CLRFLAG(oflags,OFL_HASLIGHT);
} else {
lightz = mover->z = (32l+20)<<16;
mover->shdim = 2;
mover->flags = OMF_VISIBLE;
}
health = 10;
if (GETFLAG(gameflags,GFL_NORANDOM)) {
animcount = (lshr16(mover->x)>>6) % 3;
animtrig = (lshr16(mover->y)>>6) % 3;
} else {
animcount = random(3);
animtrig = random(3);
}
fireid = -1;
}
Torcia::Torcia(int handle)
:LightActor(handle) {
if (GETFLAG(gameflags,GFL_NORANDOM)) {
animcount = (lshr16(mover->x)>>6) % 3;
animtrig = (lshr16(mover->y)>>6) % 3;
} else {
animcount = random(3);
animtrig = random(3);
}
fireid = -1;
}
void Torcia::animate() {
char lr;
if (animtrig>=100) {
if (++animtrig >= 116) {
animcount=3;
selflight=0;
//remove(); !!!
//eventmanager.sendcom(EV_ERASEACT,id);
CLRFLAG(oflags,OFL_HASLIGHT);
if (lightrange) {
remove();
lightrange=0;
place();
}
if (fireid>=0) {
stopsound(fireid);
fireid=-1;
//fireid=-1; non serve... ormai Š un object!
}
makeObject();
} else animcount = (animtrig/6) % 3;
return;
}
if (nearPlayer(128l<<FIXSHIFT)) {
if (fireid<0)
if (figstart==F_BRAZIER)
fireid=play3Dsound(mover->x,mover->y,SND_FIRE,0,mover->id,SFL_NORMAL|SFL_CONTINUE);
else
fireid=play3Dsound(mover->x,mover->y,SND_FIRE,SM_LOWVOL,mover->id,SFL_NORMAL|SFL_CONTINUE);
} else
if (fireid>=0)
if (stopsound(fireid)) fireid=-1;
if (!have_seen()) {
if (lightrange) {
remove();
lightrange=0;
place();
}
/*
if (fireid!=-1)
if (stopsound(fireid)) fireid=-1;
*/
return;
} else reset(); // !!!!
/*else {
if (nearPlayer(192l<<FIXSHIFT)) {
if (fireid==-1)
if (figstart==F_BRAZIER)
fireid=play3Dsound(mover->x,mover->y,SND_FIRE,0,0,mover->id,SFL_NORMAL|SFL_CONTINUE);
else
fireid=play3Dsound(mover->x,mover->y,SND_FIRE,16,16,mover->id,SFL_NORMAL|SFL_CONTINUE);
} else
if (fireid!=-1)
if (stopsound(fireid)) fireid=-1;
}
*/
if (figstart==F_BRAZIER) {
if (++animtrig >= 8) {
animtrig = 0;
if (++animcount > 2) animcount = 0;
}
if (!(animtrig & 3))
if (GETFLAG(gameflags,GFL_NORANDOM)) {
if (lightrange != animcount+2) {
remove();
lightrange = animcount+2;
place();
}
} else {
if (lightrange != (lr = random(2)+2)) {
remove();
lightrange = lr;
place();
}
}
} else {
if (++animtrig > 5) {
animtrig = 0;
if (++animcount > 2) animcount = 0; // !!! non voglio usare %
}
if (animtrig & 1) {
//lightpow = -2+random(5);
if (GETFLAG(gameflags,GFL_NORANDOM)) {
if (lightrange != animcount+1) {
remove();
lightrange = animcount+1;
place();
}
} else {
if (lightrange != (lr = random(2)+1)) {
remove();
lightrange = lr;
place();
}
}
}
}
}
void Torcia::handle_event(TEvent &event) {
if (!health) return;
if (event.what == EV_BOOM &&
(LABS(mover->x-event.data.pos.x)<=48l<<FIXSHIFT) &&
(LABS(mover->y-event.data.pos.y)<=48l<<FIXSHIFT)) {
if ((int)event.data.pos.z > health) {
health = 0;
animtrig = 100;
}
} else
if (event.what == EV_SCODE && event.source == SC_MNDark) {
health = 0;
animtrig = 100;
} else
if (fireid>=0 && event.what == EV_ENDSOUND && event.source==fireid)
fireid=-1;
}
int Torcia::getlightfig() {
return F_TORCLIGHT;
}
Lampadario::Lampadario(fixed px, fixed py, int fig)
:LightActor(px,py,fig,1,3,6,MVT_0)
{
object_type=OBJT_LAMPADARIO;
if (GETFLAG(gameflags,GFL_NORANDOM))
animtrig = (lshr16(px)>>6) % 6;
else
animtrig = random(6);
mover->flags = OMF_VISIBLE|OMF_HITABLE;
if (fig==F_LAMP) {
mover->z = (68l+16l)<<FIXSHIFT; //64l<<FIXSHIFT; // 48l<<16;
lightz = mover->z+(FIXONE<<1);
} else {
mover->z=32l<<FIXSHIFT;
SETFLAG(mover->flags,OMF_UNWALKABLE|OMF_HITABLE);
lightz = 52l<<FIXSHIFT;
}
lightpow = 1;
mover->shdim = 2+1; // !!!
health = 18;
decay = 0;
}
Lampadario::Lampadario(int handle)
:LightActor(handle) {
if (GETFLAG(gameflags,GFL_NORANDOM))
animtrig = (lshr16(mover->x)>>6) % 6;
else
animtrig = random(6);
decay=0;
}
void Lampadario::animate() {
char lr;
if (animtrig==127) {
makeObject();
return;
}
if (animtrig>=100) {
if (animtrig==100) {
selflight=0;
changefig(F_LAMP+2,1);
animcount=0;
animtrig++;
CLRFLAG(oflags,OFL_HASLIGHT);
if (lightrange) {
remove();
lightrange=0;
place();
}
//mover->z = 40l<<FIXSHIFT;
} else
if (animtrig == 101) {
decay+=FIXONE;
if ((mover->z -= decay)<=0l) {
animtrig++;
mover->z=0l;
changefig(F_LAMP+3,1);
play3Dsound(mover->x,mover->y,SND_GLASS,0,
mover->id,SFL_NORMAL & ~SFL_AUTOSTOP);
}
} else {
if (++animtrig >= 108) {
changefig(F_LAMPX,1);
remove();
mover->flags = OMF_VISIBLE;
place();
makeObject();
}
}
return;
}
if (!have_seen()) {
if (lightrange) {
remove();
lightrange=0;
place();
}
return;
} else reset(); // !!!!
if (++animtrig >= 8) {
animtrig = 0;
if (++animcount > 1) animcount = 0;
}
if (!(animtrig & 3)) {
if (GETFLAG(gameflags,GFL_NORANDOM)) {
if (lightrange != animcount+2) {
remove();
lightrange = animcount+2;
place();
}
} else
if (lightrange != (lr = random(2)+2)) {
remove();
lightrange = lr;
place();
}
}
}
void Lampadario::handle_event(TEvent &event) {
Object::handle_event(event);
if (animtrig<100 && event.what == EV_HIT) {
//(LABS(mover->x-event.data.pos.x)<=64l<<FIXSHIFT) &&
//(LABS(mover->y-event.data.pos.y)<=64l<<FIXSHIFT)) {
if (event.data.msg.y>7 && (health-=(int)event.data.msg.y) <= 0) {
health=0;
animtrig=100;
// if (!(oflags & OFL_ISACTOR))
makeActor();
}
} else
if (animtrig<100 && (oflags & OFL_ISACTOR) &&
event.what == EV_SCODE && event.source == SC_MNDark) {
//health = 0;
remove();
lightrange=0;
selflight=0;
place();
animcount=0;
if (figstart==F_LAMP) changefig(F_LAMPOFF,1);
else changefig(F_TRESPOLOFF,1);
CLRFLAG(oflags,OFL_HASLIGHT);
animtrig=234;
makeObject();
}
}
int Lampadario::getlightfig() {
return F_LAMPLIGHT;
}
Barile::Barile(fixed px, fixed py)
:LightActor(px,py,F_BARILE,1,0,0,MVT_1)
{
object_type=OBJT_BARILE;
health = 8;
speed = 0;
mover->z = 24l<<16;
//mover->shdim = 4; perchŠ F_BARILX Š largo 33 !
animtrig = 0;
ownerid = -1;
}
Barile::Barile(int handle)
:LightActor(handle) {
CRC_read(handle,&animtrig,sizeof(animtrig));
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&ownerid,sizeof(ownerid));
}
void Barile::save(int handle) {
LightActor::save(handle);
CRC_write(handle,&animtrig,sizeof(animtrig));
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&ownerid,sizeof(ownerid));
}
void Barile::animate() {
// fixed nx, ny;
const animlight[15] = {0,0,1,1,2,3,4,3,3,2,2,1,1,0,0};
if (health<=0) {
selflight = 8;
animcount = ++animtrig/6; // ++animtrig>>3;
}
remove();
if (speed) {
/*
nx = x+costab[angle]*speed; // <<(speed>>2));
ny = y+sintab[angle]*speed; // <<(speed>>2));
if (isfree(nx,ny,angle)) { x=nx;y=ny; } else
if (isfree(nx,y,angle)) { x=nx; } else
if (isfree(x,ny,angle)) { y=ny; }
*/
mover->fluidmove(mover->angle,lshl16(speed));
if (!(--speed) && !animtrig)
//eventmanager.sendcom(EV_ERASEACT,id);
if (!makeObject()) speed=1;
}
/*
if (animtrig==1) {
MemoryManager.reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(
x-(CosTab[angle]>>14),y-(SinTab[angle]>>14),
BOOM_2));
}
*/
// if (animtrig == 3) soundmanager->play(id,x,y,SndBoomLen,SFL_ONESHOT,SndBoom);
if (animtrig == 11) {
if (ownerid>=0)
// Sends an owner's message
eventmanager.sendpos(EV_BOOM,ownerid,mover->x,mover->y,32l);
else eventmanager.sendpos(EV_BOOM,mover->id,mover->x,mover->y,32l);
quake = 28; // !!!!!!!!!
}
if (animcount > 4) {
changefig(F_BARILX,1);
//eventmanager.sendcom(EV_ERASEACT,id);
mover->flags = OMF_VISIBLE;
if (makeObject()) {
lightrange=0;
selflight=0;
animcount=0;
}
} else lightrange = animlight[animtrig>>1];
place();
}
void Barile::handle_event(TEvent &event) {
if (animtrig) return;
Object::handle_event(event);
if (event.what == EV_HIT) {
if ((health-=event.data.msg.y) < 0) {
health=0;
ownerid = event.source;
}
makeActor(); // !!! attenti ai doppioni su mitragliata, "ma Š necessario" !
mover->angle = event.data.msg.x;
if ((speed += event.data.msg.y>>1)>9) speed=9;
} else
/*
if (event.what == EV_BOOM &&
(LABS(mover->x-event.data.pos.x)<=96l<<FIXSHIFT) &&
(LABS(mover->y-event.data.pos.y)<=96l<<FIXSHIFT)) {
if ((health-=(int)event.data.pos.z) < 0) health=0;
makeActor(); // !!! attenti ai doppioni su mitragliata, "ma Š necessario" !
} else
*/
if (event.what == EV_SCODE && event.source == SC_MNBoom) {
health = 0;
makeActor();
mover->angle = 0;
speed = 0;
}
}
Vaso::Vaso(fixed px, fixed py, int fig, byte objin)
:Actor(px,py,fig,1,MVT_1) {
object_type=OBJT_VASO;
animtrig = 0;
speed = 0;
mover->z = 24l<<FIXSHIFT;
health = 1;
if (fig == F_VASO) mover->shdim = 3;
whatin = objin;
}
Vaso::Vaso(int handle)
:Actor(handle) {
CRC_read(handle,&animtrig,sizeof(animtrig));
CRC_read(handle,&speed,sizeof(speed));
CRC_read(handle,&whatin,sizeof(whatin));
}
void Vaso::save(int handle) {
Actor::save(handle);
CRC_write(handle,&animtrig,sizeof(animtrig));
CRC_write(handle,&speed,sizeof(speed));
CRC_write(handle,&whatin,sizeof(whatin));
}
void Vaso::animate() {
if (health<=0)
animcount = (++animtrig/6)+1; // ++animtrig>>3;
remove();
if (speed) {
mover->fluidmove(mover->angle,lshl16(speed));
if (!(--speed) && !animtrig)
if (!makeObject()) speed++;
}
// if (animtrig == 3) soundmanager->play(id,x,y,SndBoomLen,SFL_ONESHOT,SndBoom);
if ((figstart == F_VASO && animcount >= 5) ||
(figstart == F_PIANTA && animcount >= 4)) {
mover->flags = OMF_VISIBLE;
if (!makeObject()) animtrig--;
}
place();
}
void Vaso::handle_event(TEvent &event) {
if (animtrig) return;
Object::handle_event(event);
if (event.what == EV_HIT) {
if ((health-=event.data.msg.y) < 0) {
health=0;
if (figstart==F_VASO)
play3Dsound(mover->x,mover->y,SND_VASO1,SM_NORMVOL,mover->id,SFL_NORMAL & ~SFL_AUTOSTOP);
else
play3Dsound(mover->x,mover->y,SND_VASO2,SM_NORMVOL,mover->id,SFL_NORMAL & ~SFL_AUTOSTOP);
}
makeActor(); // !!! attenti ai doppioni su mitragliata, "ma Š necessario" !
animtrig++; // Questo evita i doppioni !
mover->angle = event.data.msg.x;
if ((speed += event.data.msg.y>>1)>9) speed=9;
remove();
mover->flags = OMF_VISIBLE;
place();
// Eject souvenirs
//if (figstart == F_PIANTA) {
int angle,
strength = event.data.msg.y;
word fig;
Object *obj;
if (!GETFLAG(gameflags,GFL_NORANDOM))
angle = anglesub(angleadd(event.data.msg.x,ANG180+(ANG30>>1)),random(ANG30));
else
angle = angleadd(event.data.msg.x,ANG180);
/*
int x;
if (norandom) x = (lshr16(mover->x + mover->y) >> 6) % 9;
else x = random(9);
*/
switch (whatin) {
case 0: fig = 0; break;
case 1: fig = F_FUCILE; break;
case 2: fig = F_MITRA; break;
case 3: fig = F_BAZOOKA; break;
case 4: fig = F_BOMB; break;
case 5: fig = F_CARTUCCIA1; break;
case 6: fig = F_CARTUCCIA2; break;
case 7: fig = F_CARTUCCIA3; break;
case 8: fig = F_CARTUCCIA4; break;
case 9: fig=0; break;// BOOM, now do nothing
}
if (fig) {
delete mm_reserve(sizeof(Object));
obj = new Object(mover->x,mover->y,fig,1,MVT_0);
CLRFLAG(obj->mover->flags,OMF_UNWALKABLE|OMF_HITABLE);
SETFLAG(obj->oflags,OFL_TAKEABLE);
objectslist.put(obj);
delete mm_reserve(sizeof(ObjMover));
objectslist.put(new ObjMover(obj->getid(),angle,strength));
} else
if (whatin==9) {
eventmanager.sendpos(EV_BOOM,mover->id,mover->x,mover->y,
(long)ArmList[ARM_BAZOOKA].power);
delete mm_reserve(sizeof(FireBoom));
objectslist.put(new FireBoom(mover->x,mover->y,mover->z,
mover->angle,BOOM_MISSIL));
quake=14;
}
//}
}
/*
if (event.what == EV_BOOM &&
(LABS(mover->x-event.data.pos.x)<=96l<<FIXSHIFT) &&
(LABS(mover->y-event.data.pos.y)<=96l<<FIXSHIFT)) {
if ((health-=(int)event.data.pos.z) < 0) health=0;
makeActor(); // !!! attenti ai doppioni su mitragliata, "ma Š necessario" !
} else
*/
/*
if (event.what == EV_SCODE && event.source == SC_ADBoom) {
health = 0;
makeActor();
speed = 0;
}
*/
}