diff --git a/Graphics/characters/Eyeball/AnimList.Txt b/Graphics/characters/Eyeball/AnimList.Txt index fd0299275..631f64c0b 100644 --- a/Graphics/characters/Eyeball/AnimList.Txt +++ b/Graphics/characters/Eyeball/AnimList.Txt @@ -1,2 +1,2 @@ -Roll +Static Stalk diff --git a/data/DataCache.scr b/data/DataCache.scr index 33b4f95c2..d618b78cb 100644 --- a/data/DataCache.scr +++ b/data/DataCache.scr @@ -176,7 +176,6 @@ actors/BALLBLOB.SBK actors/CATERPILLAR.SBK actors/CLAM.SBK actors/DUSTDEVIL.SBK -actors/EYEBALL.SBK actors/FLAMINGSKULL.SBK actors/FLYINGDUTCHMAN.SBK actors/GHOST.SBK diff --git a/makefile.gfx b/makefile.gfx index f0655ee18..3d95e1417 100644 --- a/makefile.gfx +++ b/makefile.gfx @@ -110,14 +110,14 @@ ACTOR_DIRS_TO_MAKE := $(ACTOR_MAKEFILE_DIR) $(ACTOR_OUT_DIR) ACTOR_SPONGEBOB := SpongeBob SpongeBob_CoralBlower SpongeBob_JellyLauncher SpongeBob_Net SpongeBob_Glove SpongeBob_Glasses SpongeBob_JellyFish ACTOR_NPC := BarnacleBoy Krusty Squidward Gary Sandy Patrick MermaidMan -ACTOR_ENEMY := Anenome BabyOctopus Ballblob Caterpillar clam Dustdevil Eyeball \ +ACTOR_ENEMY := Anenome BabyOctopus Ballblob Caterpillar clam Dustdevil \ Flamingskull FlyingDutchman Ghost HermitCrab IronDogFish Lrgjellyfish \ PuffaFish Sharkman Skeletalfish SpiderCrab SpikeyAnenome Stomper \ SharkSub Motherjellyfish SeaSnake # Boogermonster GiantWorm Jellyfish2 Motherjellyfish Nautilus Neptune SeaSnake SharkSub -ACTOR_SPRITES := Jellyfish1 Squiddart Plankton Butterfly Shell +ACTOR_SPRITES := Jellyfish1 Squiddart Plankton Butterfly Shell Eyeball ACTOR_SPR_LIST := $(foreach ACTOR,$(ACTOR_SPRITES), $(ACTOR_IN_DIR)/$(ACTOR)/$(ACTOR_SPRITE_DIR)/$(ACTOR)_*.bmp) ACTOR_SPR_DEP := $(foreach ACTOR,$(ACTOR_SPRITES), $(ACTOR_IN_DIR)/$(ACTOR)/$(ACTOR_SPRITE_DIR)/*) diff --git a/source/enemy/neyeball.cpp b/source/enemy/neyeball.cpp index 8df6f403d..c6d5a4605 100644 --- a/source/enemy/neyeball.cpp +++ b/source/enemy/neyeball.cpp @@ -31,27 +31,55 @@ #include "projectl\projectl.h" #endif +#ifndef __SPR_SPRITES_H__ +#include +#endif + +#ifndef __VID_HEADER_ +#include "system\vid.h" +#endif + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void CNpcEyeballEnemy::processEnemyCollision( CThing *thisThing ) { // do nothing } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void CNpcEyeballEnemy::postInit() { -return; + DVECTOR eyeballPos = Pos; + m_fireHeading = m_heading; + m_drawRotation = ( m_heading + 1024 ) & 4095; + + eyeballPos.vx += ( EYEBALL_DIST * rcos( m_heading ) ) >> 12; + eyeballPos.vy += ( EYEBALL_DIST * rsin( m_heading ) ) >> 12; + CProjectile *projectile; projectile = new ( "eyeball projectile" ) CProjectile; - projectile->init( Pos, m_fireHeading, CProjectile::PROJECTILE_FIXED, CProjectile::PROJECTILE_INFINITE_LIFE ); + projectile->init( eyeballPos, m_fireHeading, CProjectile::PROJECTILE_FIXED, CProjectile::PROJECTILE_INFINITE_LIFE ); projectile->setLayerCollision( m_layerCollision ); + projectile->setGraphic( FRM_EYEBALL_STATIC ); addChild( projectile ); } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcEyeballEnemy::shutdown() +{ + deleteAllChild(); + CNpcEnemy::shutdown(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool CNpcEyeballEnemy::processSensor() { -return(false); switch( m_sensorFunc ) { case NPC_SENSOR_NONE: @@ -73,9 +101,10 @@ return(false); } } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void CNpcEyeballEnemy::processClose( int _frames ) { -return; if ( Next ) { CProjectile *projectile; @@ -90,12 +119,218 @@ return; } else { + DVECTOR eyeballPos = Pos; + + eyeballPos.vx += ( EYEBALL_DIST * rcos( m_heading ) ) >> 12; + eyeballPos.vy += ( EYEBALL_DIST * rsin( m_heading ) ) >> 12; + CProjectile *projectile; projectile = new ( "eyeball projectile" ) CProjectile; - projectile->init( Pos, m_fireHeading, CProjectile::PROJECTILE_USER_SEEK, CProjectile::PROJECTILE_INFINITE_LIFE ); + projectile->init( eyeballPos, m_fireHeading, CProjectile::PROJECTILE_USER_SEEK, CProjectile::PROJECTILE_INFINITE_LIFE ); projectile->setLayerCollision( m_layerCollision ); + projectile->setGraphic( FRM_EYEBALL_STATIC ); projectile->setState( CProjectile::PROJECTILE_ATTACK ); addChild( projectile ); } -} \ No newline at end of file +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcEyeballEnemy::render() +{ + SprFrame = NULL; + + if ( m_isActive ) + { + CEnemyThing::render(); + + if (canRender()) + { + DVECTOR &renderPos=getRenderPos(); + + SprFrame = m_spriteBank->printRotatedScaledSprite( FRM_EYEBALL_STALK, renderPos.vx, renderPos.vy, 4096, 4096, m_drawRotation, 10); + + // get xmax, xmin, ymax, ymin + + s32 XMax; + s32 XMin; + + s32 YMax; + s32 YMin; + + XMin=SprFrame->x0; + if (XMin>SprFrame->x1) XMin=SprFrame->x1; + if (XMin>SprFrame->x2) XMin=SprFrame->x2; + if (XMin>SprFrame->x3) XMin=SprFrame->x3; + XMax=SprFrame->x0; + if (XMaxx1) XMax=SprFrame->x1; + if (XMaxx2) XMax=SprFrame->x2; + if (XMaxx3) XMax=SprFrame->x3; + YMin=SprFrame->y0; + if (YMin>SprFrame->y1) YMin=SprFrame->y1; + if (YMin>SprFrame->y2) YMin=SprFrame->y2; + if (YMin>SprFrame->y3) YMin=SprFrame->y3; + YMax=SprFrame->y0; + if (YMaxy1) YMax=SprFrame->y1; + if (YMaxy2) YMax=SprFrame->y2; + if (YMaxy3) YMax=SprFrame->y3; + + XMax -= renderPos.vx; + XMin -= renderPos.vx; + YMax -= renderPos.vy; + YMin -= renderPos.vy; + + setCollisionSize( ( XMax - XMin ), ( YMax - YMin ) ); + setCollisionCentreOffset( ( XMax + XMin ) >> 1, ( YMax + YMin ) >> 1 ); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcEyeballEnemy::processEvent( GAME_EVENT evt, CThing *sourceThing ) +{ + switch( evt ) + { + case PROJECTILE_RETURNED_TO_SOURCE_EVENT: + { + m_controlFunc = NPC_CONTROL_MOVEMENT; + m_timerFunc = NPC_TIMER_ATTACK_DONE; + m_timerTimer = GameState::getOneSecondInFrames(); + m_sensorFunc = NPC_SENSOR_NONE; + + //removeChild( sourceThing ); + //sourceThing->shutdown(); + //delete sourceThing; + + CProjectile *projectile; + projectile = (CProjectile *) sourceThing; + projectile->setMovementType( CProjectile::PROJECTILE_FIXED ); + + DVECTOR eyeballPos = Pos; + + eyeballPos.vx += ( EYEBALL_DIST * rcos( m_heading ) ) >> 12; + eyeballPos.vy += ( EYEBALL_DIST * rsin( m_heading ) ) >> 12; + + projectile->setPosition( eyeballPos ); + + break; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CNpcEyeballEnemy::processShot( int _frames ) +{ + switch ( m_state ) + { + case NPC_GENERIC_HIT_CHECK_HEALTH: + { + if ( CLevel::getCurrentChapter() == 1 && CLevel::getCurrentChapterLevel() == 1 ) + { + m_state = NPC_GENERIC_HIT_DEATH_START; + } + else + { + m_health -= 5; + + if ( m_health < 0 ) + { + m_state = NPC_GENERIC_HIT_DEATH_START; + } + else + { + m_state = 0; + m_controlFunc = NPC_CONTROL_MOVEMENT; + } + } + + break; + } + + case NPC_GENERIC_HIT_DEATH_START: + { + m_animPlaying = true; + m_animNo = m_data[m_type].dieAnim; + m_frame = 0; + m_state = NPC_GENERIC_HIT_DEATH_END; + + m_isDying = true; + m_speed = -5; + + if (m_data[m_type].skelType) + { + m_actorGfx->SetOtPos( 0 ); + } + + if ( Next ) + { + CProjectile *projectile; + + projectile = (CProjectile *) Next; + + if ( projectile->getMovementType() != CProjectile::PROJECTILE_FIXED ) + { + projectile->setMovementType( CProjectile::PROJECTILE_DUMBFIRE ); + projectile->setLifeTime( CProjectile::PROJECTILE_FINITE_LIFE ); + + removeChild( Next ); + } + } + + break; + } + + case NPC_GENERIC_HIT_DEATH_END: + { + m_drawRotation += 64 * _frames; + m_drawRotation &= 4095; + + m_heading = m_drawRotation - 1024; + m_heading &= 4095; + + Pos.vy += m_speed * _frames; + + if ( m_speed < 5 ) + { + m_speed++; + } + + if ( Next ) + { + CProjectile *projectile; + + projectile = (CProjectile *) Next; + + DVECTOR eyeballPos = Pos; + + eyeballPos.vx += ( EYEBALL_DIST * rcos( m_heading ) ) >> 12; + eyeballPos.vy += ( EYEBALL_DIST * rsin( m_heading ) ) >> 12; + + projectile->setPosition( eyeballPos ); + projectile->setHeading( m_heading ); + } + + DVECTOR offset = CLevel::getCameraPos(); + + if ( Pos.vy - offset.vy > VidGetScrH() ) + { + if ( m_data[m_type].respawning ) + { + m_isActive = false; + + m_timerFunc = NPC_TIMER_RESPAWN; + m_timerTimer = 4 * GameState::getOneSecondInFrames(); + } + else + { + setToShutdown(); + } + } + + break; + } + } +} diff --git a/source/enemy/neyeball.h b/source/enemy/neyeball.h index 5548c175c..edaa8b0e9 100644 --- a/source/enemy/neyeball.h +++ b/source/enemy/neyeball.h @@ -17,15 +17,23 @@ class CNpcEyeballEnemy : public CNpcEnemy { public: - virtual void render(){} - + virtual void render(); virtual void postInit(); + virtual void shutdown(); + virtual int getFrameCount() {return( 1 );} + virtual void processEvent( GAME_EVENT evt, CThing *sourceThing ); protected: virtual void processEnemyCollision( CThing *thisThing ); virtual bool processSensor(); virtual void processClose( int _frames ); + virtual void processShot( int _frames ); s32 m_fireHeading; + + enum + { + EYEBALL_DIST = 30, + }; }; #endif \ No newline at end of file diff --git a/source/enemy/npc.cpp b/source/enemy/npc.cpp index 908023d2c..fa85f0427 100644 --- a/source/enemy/npc.cpp +++ b/source/enemy/npc.cpp @@ -577,7 +577,7 @@ void CNpcEnemy::setStartPos( s32 xPos, s32 yPos ) void CNpcEnemy::setHeading( s32 xPos, s32 yPos ) { - m_heading = ratan2( ( yPos << 4 ) - Pos.vy, ( xPos << 4 ) - Pos.vx ); + m_heading = ( ratan2( ( yPos << 4 ) - Pos.vy, ( xPos << 4 ) - Pos.vx ) ) & 4095; } @@ -628,6 +628,7 @@ void CNpcEnemy::init() m_isCaught = false; m_isBlowerOn = false; m_speed = m_data[m_type].speed; + m_heading = 0; updateCollisionArea(); } diff --git a/source/enemy/npc.h b/source/enemy/npc.h index f0e9d472b..910c1276f 100644 --- a/source/enemy/npc.h +++ b/source/enemy/npc.h @@ -94,7 +94,7 @@ public: virtual u8 canCollideWithEnemy() {return( true );} virtual void think(int _frames); virtual void render(); - void processEvent( GAME_EVENT evt, CThing *sourceThing ); + virtual void processEvent( GAME_EVENT evt, CThing *sourceThing ); void setLayerCollision( class CLayerCollision *_layer ) {m_layerCollision=_layer;} void setType( NPC_UNIT_TYPE newType ) {m_type = newType;} NPC_UNIT_TYPE getType() {return( m_type );} diff --git a/source/enemy/npcdata.cpp b/source/enemy/npcdata.cpp index 8da2ec4a2..15bd1627b 100644 --- a/source/enemy/npcdata.cpp +++ b/source/enemy/npcdata.cpp @@ -43,10 +43,6 @@ #include #endif -#ifndef __ANIM_EYEBALL_HEADER__ -#include -#endif - #ifndef __ANIM_FLAMINGSKULL_HEADER__ #include #endif @@ -574,8 +570,8 @@ CNpcEnemy::NPC_DATA CNpcEnemy::m_data[NPC_UNIT_TYPE_MAX] = }, { // NPC_EYEBALL - ACTORS_EYEBALL_SBK, - ANIM_EYEBALL_STALK, + 0,//ACTORS_EYEBALL_SBK, + 0, NPC_SENSOR_USER_CLOSE, NPC_MOVEMENT_STATIC, NPC_CLOSE_NONE, diff --git a/source/projectl/projectl.cpp b/source/projectl/projectl.cpp index 18e4cee8a..797841cca 100644 --- a/source/projectl/projectl.cpp +++ b/source/projectl/projectl.cpp @@ -57,8 +57,9 @@ void CProjectile::init() m_spriteBank=new ("projectile sprites") SpriteBank(); m_spriteBank->load(SPRITES_SPRITES_SPR); + m_spriteFrame = FRM__SPIKE; - m_heading = 0; + m_initHeading = m_heading = 0; m_lifetime = GameState::getOneSecondInFrames() * 2; m_movementType = PROJECTILE_DUMBFIRE; m_lifetimeType = PROJECTILE_FINITE_LIFE; @@ -74,7 +75,7 @@ void CProjectile::init( DVECTOR initPos, s16 initHeading ) { init(); - m_heading = initHeading; + m_initHeading = m_heading = initHeading; m_initPos = Pos = initPos; } @@ -100,6 +101,11 @@ void CProjectile::shutdown() CEnemyProjectileThing::shutdown(); } +void CProjectile::setGraphic( int frame ) +{ + m_spriteFrame = frame; +} + bool CProjectile::processTargetSeek( int _frames, DVECTOR targetPos ) { s32 moveX = 0, moveY = 0; @@ -253,9 +259,10 @@ void CProjectile::think(int _frames) { case PROJECTILE_RETURN: { - if ( processTargetSeek( _frames, Parent->getPos() ) ) + if ( processTargetSeek( _frames, m_initPos ) ) { Parent->processEvent( PROJECTILE_RETURNED_TO_SOURCE_EVENT, this ); + m_heading = m_initHeading; } break; @@ -352,7 +359,7 @@ void CProjectile::render() //m_spriteBank->printFT4(FRM__SPIKE,x,y,0,0,0); - frameHdr = m_spriteBank->getFrameHeader(FRM__SPIKE); + frameHdr = m_spriteBank->getFrameHeader( m_spriteFrame ); m_spriteBank->printRotatedScaledSprite( frameHdr, x, y, 4096, 4096, m_heading, m_ot ); } diff --git a/source/projectl/projectl.h b/source/projectl/projectl.h index caac8b5ea..8dc07e5d6 100644 --- a/source/projectl/projectl.h +++ b/source/projectl/projectl.h @@ -49,7 +49,6 @@ public: void init( DVECTOR initPos, s16 initHeading, PROJECTILE_MOVEMENT_TYPE initMoveType, PROJECTILE_LIFETIME_TYPE initLifeType, s32 initLifetime ); void shutdown(); void think(int _frames); - void setPos( DVECTOR newPos ) {Pos = newPos;} virtual void render(); void processEvent( GAME_EVENT evt, CThing *sourceThing ); void setMovementType( PROJECTILE_MOVEMENT_TYPE moveType ); @@ -57,8 +56,10 @@ public: void setState( PROJECTILE_STATE newState ); void setLifeTime( PROJECTILE_LIFETIME_TYPE lifeType ); void setPosition( DVECTOR newPos ); + void setHeading( s16 newHeading ) {m_heading = newHeading;} void setLayerCollision( class CLayerCollision *_layer ) {m_layerCollision=_layer;} void setOt( u8 newOt ) {m_ot=newOt;} + void setGraphic( int frame ); private: class CLayerCollision *m_layerCollision; @@ -71,6 +72,7 @@ protected: class SpriteBank *m_spriteBank; DVECTOR m_initPos; s16 m_heading; + s16 m_initHeading; s32 m_lifetime; s32 m_extension; PROJECTILE_MOVEMENT_TYPE m_movementType; @@ -78,6 +80,7 @@ protected: PROJECTILE_STATE m_state; u16 m_turnSpeed; u8 m_ot; + int m_spriteFrame; }; /*****************************************************************************/