SBSPSS/source/platform/platform.cpp

1386 lines
29 KiB
C++
Raw Normal View History

2001-04-23 17:27:50 +02:00
/*=========================================================================
2001-04-23 22:40:13 +02:00
platform.cpp
2001-04-23 17:27:50 +02:00
Author: CRB
Created:
Project: Spongebob
Purpose:
Copyright (c) 2000 Climax Development Ltd
===========================================================================*/
2001-04-23 22:40:13 +02:00
#include "platform\platform.h"
2001-04-23 17:27:50 +02:00
#ifndef __LEVEL_LEVEL_H__
#include "level\level.h"
#endif
#ifndef __FILE_EQUATES_H__
#include <biglump.h>
#endif
#ifndef __GAME_GAME_H__
#include "game\game.h"
#endif
#ifndef __PLAYER_PLAYER_H__
#include "player\player.h"
#endif
2001-05-25 21:08:35 +02:00
#ifndef __FRIEND_FRIEND_H__
#include "friend\friend.h"
#endif
2001-05-08 18:25:45 +02:00
#ifndef __HAZARD_HAZARD_H__
#include "hazard\hazard.h"
#endif
2001-04-23 17:27:50 +02:00
#ifndef __ENEMY_NPCPATH_H__
#include "enemy\npcpath.h"
#endif
#ifndef __UTILS_HEADER__
#include "utils\utils.h"
#endif
#include "Gfx\actor.h"
#ifndef __VID_HEADER_
#include "system\vid.h"
#endif
2001-04-23 22:40:13 +02:00
#ifndef __PLATFORM_PLINEAR_H__
#include "platform\plinear.h"
#endif
#ifndef __PLATFORM_PCIRCULR_H__
#include "platform\pcirculr.h"
#endif
#ifndef __PLATFORM_PBUBBLE_H__
#include "platform\pbubble.h"
#endif
#ifndef __PLATFORM_PCBUBBLE_H__
#include "platform\pcbubble.h"
#endif
#ifndef __PLATFORM_PFISHHK_H__
#include "platform\pfishhk.h"
#endif
#ifndef __PLATFORM_PRETRACT_H__
#include "platform\pretract.h"
#endif
#ifndef __PLATFORM_PGEYSER_H__
#include "platform\pgeyser.h"
#endif
#ifndef __PLATFORM_PBOB_H__
#include "platform\pbob.h"
#endif
#ifndef __PLATFORM_PFALLING_H__
#include "platform\pfalling.h"
#endif
2001-04-25 00:05:29 +02:00
#ifndef __PLATFORM_PPENDULM_H__
#include "platform\ppendulm.h"
#endif
2001-04-25 21:22:15 +02:00
#ifndef __PLATFORM_PBRANCH_H__
#include "platform\pbranch.h"
#endif
2001-04-25 22:52:36 +02:00
#ifndef __PLATFORM_PCART_H__
#include "platform\pcart.h"
#endif
2001-04-30 18:05:49 +02:00
#ifndef __PLATFORM_PSEESAW_H__
#include "platform\pseesaw.h"
#endif
2001-05-01 22:45:03 +02:00
#ifndef __PLATFORM_PBOUNCE_H__
#include "platform\pbounce.h"
#endif
2001-05-02 21:52:33 +02:00
#ifndef __PLATFORM_PDUAL_H__
#include "platform\pdual.h"
#endif
2001-04-23 22:40:13 +02:00
#ifndef __PLATFORM_PPLAYER_H__
#include "platform\pplayer.h"
#endif
2001-05-03 21:01:59 +02:00
#ifndef __PLATFORM_PFGEN_H__
#include "platform\pfgen.h"
#endif
2001-05-04 16:49:15 +02:00
#ifndef __PLATFORM_PRAFT_H__
#include "platform\praft.h"
#endif
2001-05-04 20:54:27 +02:00
#ifndef __PLATFORM_PLANTERN_H__
#include "platform\plantern.h"
#endif
2001-05-05 01:12:26 +02:00
#ifndef __PLATFORM_PBGEYSER_H__
#include "platform\pbgeyser.h"
#endif
2001-05-05 01:56:39 +02:00
#ifndef __PLATFORM_PLEAF_H__
#include "platform\pleaf.h"
#endif
2001-04-27 22:13:09 +02:00
2001-05-05 15:54:34 +02:00
#ifndef __PLATFORM_PBWHEEL_H__
#include "platform\pbwheel.h"
#endif
2001-05-05 18:47:51 +02:00
#ifndef __PLATFORM_PSBARREL_H__
#include "platform\psbarrel.h"
#endif
2001-05-14 16:21:04 +02:00
#ifndef __PLATFORM_PJELLFSH_H__
#include "platform\pjellfsh.h"
#endif
2001-05-23 16:46:23 +02:00
#ifndef __PLATFORM_PFISHHK3_H__
#include "platform\pfishhk3.h"
#endif
2001-05-23 18:01:00 +02:00
#ifndef __PLATFORM_PRBRIDGE_H__
#include "platform\prbridge.h"
#endif
2001-05-23 23:27:29 +02:00
#ifndef __PLATFORM_PBALOON_H__
#include "platform\pbaloon.h"
#endif
2001-05-24 01:16:43 +02:00
#ifndef __PLATFORM_PTRPDOOR_H__
#include "platform\ptrpdoor.h"
#endif
2001-05-29 17:29:56 +02:00
#ifndef __PLATFORM_PCONVEYR_H__
#include "platform\pconveyr.h"
#endif
#ifndef __PLATFORM_PFALLNOR_H__
#include "platform\pfallnor.h"
#endif
2001-06-05 22:44:30 +02:00
#ifndef __PLATFORM_PDROP_H__
#include "platform\pdrop.h"
#endif
2001-06-05 23:21:23 +02:00
#ifndef __PLATFORM_PSSWITCH_H__
#include "platform\psswitch.h"
#endif
2001-06-06 16:14:47 +02:00
#ifndef __PLATFORM_PLIFT_H__
#include "platform\plift.h"
#endif
2001-06-06 17:04:20 +02:00
#ifndef __PLATFORM_PLURVE_H__
#include "platform\plurve.h"
#endif
2001-06-08 16:33:43 +02:00
#ifndef __PLATFORM_PSOIL_H__
#include "platform\psoil.h"
#endif
2001-06-11 21:32:41 +02:00
#ifndef __PLATFORM_PBUBTUBE_H__
#include "platform\pbubtube.h"
#endif
2001-06-14 18:07:48 +02:00
#ifndef __PLATFORM_PCLAM_H__
#include "platform\pclam.h"
#endif
#ifndef __PLATFORM_PPLAYER_H__
#include "platform\pplayer.h"
#endif
2001-07-03 20:32:04 +02:00
#ifndef __PLATFORM_PGBUBBLE_H__
#include "platform\pgbubble.h"
#endif
2001-07-05 22:08:39 +02:00
#ifndef __PLATFORM_PFBLOCK_H__
#include "platform\pfblock.h"
#endif
2001-07-13 17:18:50 +02:00
#ifndef __PLATFORM_PGHOST_H__
#include "platform\pghost.h"
#endif
2001-05-05 21:08:02 +02:00
#include "fx\fx.h"
#include "fx\fxjfish.h"
2001-04-27 22:13:09 +02:00
2001-04-23 17:27:50 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-05-25 22:00:13 +02:00
CNpcPlatform *CNpcPlatform::Create(int Type)
2001-04-23 22:40:13 +02:00
{
CNpcPlatform *platform;
2001-05-25 20:43:47 +02:00
platform = (CNpcPlatform*)CThingManager::GetThing(CThing::TYPE_PLATFORM,Type);
if (!platform)
switch( Type )
2001-04-23 22:40:13 +02:00
{
case NPC_LINEAR_PLATFORM:
{
platform = new ("linear platform") CNpcLinearPlatform;
break;
}
case NPC_CIRCULAR_PLATFORM:
{
platform = new ("circular platform") CNpcCircularPlatform;
break;
}
case NPC_BUBBLE_PLATFORM:
{
2001-07-03 20:32:04 +02:00
platform = new ("geyser bubble platform") CNpcGeyserBubblePlatform;
2001-04-23 22:40:13 +02:00
break;
}
case NPC_COLLAPSING_BUBBLE_PLATFORM:
{
platform = new ("collapsing bubble platform") CNpcCollapsingBubblePlatform;
break;
}
2001-06-01 20:36:50 +02:00
case NPC_COLLAPSING_ACRID_PLATFORM:
{
platform = new ("collapsing bubble platform") CNpcCollapsingAcridPlatform;
break;
}
2001-04-23 22:40:13 +02:00
case NPC_FISH_HOOK_PLATFORM:
{
platform = new ("fish hook platform") CNpcFishHookPlatform;
break;
}
case NPC_RETRACTING_PLATFORM:
{
platform = new ("retracting platform") CNpcRetractingPlatform;
break;
}
case NPC_GEYSER_PLATFORM:
{
platform = new ("geyser platform") CNpcGeyserPlatform;
break;
}
case NPC_BOBBING_PLATFORM:
{
platform = new ("bobbing platform") CNpcBobbingPlatform;
break;
}
2001-05-01 16:24:48 +02:00
case NPC_OILDRUM_PLATFORM:
case NPC_CRATE_PLATFORM:
2001-04-23 22:40:13 +02:00
case NPC_FALLING_PLATFORM:
{
2001-05-29 17:29:56 +02:00
platform = new ("falling platform") CNpcFallingNoRespawnPlatform;
2001-04-23 22:40:13 +02:00
break;
}
2001-04-25 00:05:29 +02:00
case NPC_FISH_HOOK_2_PLATFORM:
{
platform = new ("fish hook 2 platform") CNpcPendulumPlatform;
break;
}
2001-04-25 21:22:15 +02:00
case NPC_BRANCH_PLATFORM:
{
platform = new ("branch platform") CNpcBranchPlatform;
break;
}
2001-04-25 22:52:36 +02:00
case NPC_CART_PLATFORM:
{
2001-07-16 22:25:19 +02:00
//platform = new ("cart platform") CNpcCartPlatform;
platform = new ("ghost train platform") CNpcGhostTrainPlatform;
2001-04-25 22:52:36 +02:00
break;
}
2001-05-25 21:08:35 +02:00
2001-04-30 18:05:49 +02:00
case NPC_SEESAW_PLATFORM:
{
platform = new ("seesaw platform") CNpcSeesawPlatform;
break;
}
2001-04-25 22:52:36 +02:00
2001-05-01 22:45:03 +02:00
case NPC_BOUNCE_PLATFORM:
{
platform = new ("bounce platform") CNpcBouncePlatform;
break;
}
2001-05-02 21:52:33 +02:00
case NPC_DUAL_PLATFORM:
{
2001-05-25 22:00:13 +02:00
platform = new ("dual platform master") CNpcDualPlatform;
2001-05-02 21:52:33 +02:00
break;
}
2001-05-03 21:01:59 +02:00
case NPC_OILDRUM_GENERATOR:
{
CNpcFallingPlatformGenerator *generator;
generator = new ("oildrum generator") CNpcFallingPlatformGenerator;
generator->setTargetType( NPC_OILDRUM_PLATFORM );
platform = generator;
break;
}
case NPC_CRATE_GENERATOR:
{
CNpcFallingPlatformGenerator *generator;
generator = new ("crate generator") CNpcFallingPlatformGenerator;
generator->setTargetType( NPC_CRATE_PLATFORM );
platform = generator;
break;
}
2001-05-04 16:49:15 +02:00
case NPC_RAFT_PLATFORM:
{
platform = new ("raft platform") CNpcRaftPlatform;
break;
}
2001-05-04 18:47:09 +02:00
case NPC_VERTICAL_OILDRUM_GENERATOR:
{
CNpcFallingPlatformGenerator *generator;
generator = new ("vertical oildrum generator") CNpcFallingPlatformGenerator;
generator->setTargetType( NPC_VERTICAL_OILDRUM_PLATFORM );
platform = generator;
break;
}
2001-05-05 01:12:26 +02:00
case NPC_BUBBLE_GEYSER_GENERATOR:
{
CNpcGeyserPlatformGenerator *generator;
generator = new ("bubble geyser generator") CNpcGeyserPlatformGenerator;
generator->setTargetType( NPC_BUBBLE_PLATFORM );
platform = generator;
break;
}
2001-05-04 20:54:27 +02:00
case NPC_LANTERN_PLATFORM:
{
platform = new ("lantern platform") CNpcLanternPlatform;
break;
}
2001-05-05 01:56:39 +02:00
case NPC_LEAF_PLATFORM:
{
platform = new ("leaf platform") CNpcLeafPlatform;
break;
}
2001-05-05 15:54:34 +02:00
case NPC_BIG_WHEEL_PLATFORM:
{
platform = new ("big wheel platform") CNpcBigWheelPlatform;
break;
}
2001-05-05 18:47:51 +02:00
case NPC_STEERABLE_BARREL_PLATFORM:
{
platform = new ("steerable barrel platform") CNpcSteerableBarrelPlatform;
break;
}
2001-05-14 16:21:04 +02:00
case NPC_JELLYFISH_PLATFORM:
{
platform = new ("jellyfish platform") CNpcJellyfishPlatform;
break;
}
2001-05-23 16:46:23 +02:00
case NPC_FISH_HOOK_3_PLATFORM:
{
platform = new ("fish hook 3 platform") CNpcFishHook3Platform;
break;
}
2001-05-23 18:01:00 +02:00
case NPC_RISING_BRIDGE_PLATFORM:
{
platform = new ("rising bridge platform") CNpcRisingBridgePlatform;
break;
}
2001-05-23 23:27:29 +02:00
case NPC_BALLOON_BRIDGE_PLATFORM:
{
platform = new ("balloon bridge platform") CNpcBalloonBridgePlatform;
break;
}
2001-05-24 01:16:43 +02:00
case NPC_TRAPDOOR_PLATFORM:
{
platform = new ("trapdoor platform") CNpcTrapdoorPlatform;
break;
}
2001-05-29 17:29:56 +02:00
case NPC_CONVEYOR_GENERATOR:
{
platform = new ("conveyor generator") CNpcConveyorPlatformGenerator;
break;
}
case NPC_CONVEYOR_PLATFORM:
{
platform = new ("conveyor platform") CNpcConveyorPlatform;
break;
}
2001-06-05 22:44:30 +02:00
case NPC_DROP_PLATFORM:
{
platform = new ("drop platform") CNpcDropPlatform;
break;
}
2001-06-05 23:21:23 +02:00
case NPC_STEAM_SWITCH_PLATFORM:
{
platform = new ("steam switch platform") CNpcSteamSwitchPlatform;
break;
}
2001-06-06 16:14:47 +02:00
case NPC_LIFT_PLATFORM:
{
platform = new ("lift platform") CNpcLiftPlatform;
break;
}
2001-06-06 17:04:20 +02:00
case NPC_LOVE_BOAT_PLATFORM:
{
platform = new ("love boat platform") CNpcLoveBoatPlatform;
break;
}
2001-06-08 16:33:43 +02:00
case NPC_STEERABLE_OILDRUM_PLATFORM:
{
platform = new ("steerable oildrum platform") CNpcSteerableOildrumPlatform;
break;
}
2001-06-11 21:32:41 +02:00
case NPC_BUBBLE_TUBE_PLATFORM:
{
platform = new ("bubble tube platform") CNpcBubbleTubePlatform;
break;
}
2001-07-05 22:08:39 +02:00
case NPC_FALLING_BLOCK_PLATFORM:
{
platform = new ("falling block platform") CNpcFallingBlockPlatform;
break;
}
2001-07-13 17:18:50 +02:00
case NPC_GHOST_TRAIN_PLATFORM:
{
platform = new ("ghost train platform") CNpcGhostTrainPlatform;
break;
}
2001-06-14 18:07:48 +02:00
case NPC_CLAM_PLATFORM:
{
platform = new ("clam platform") CNpcClamPlatform;
break;
}
case NPC_PLAYER_BUBBLE_PLATFORM:
{
platform = new ("player bubble platform") CNpcPlayerBubblePlatform;
break;
}
2001-04-23 22:40:13 +02:00
default:
{
2001-04-25 00:05:29 +02:00
ASSERT( 0 );
2001-04-23 22:40:13 +02:00
platform = new ("platform") CNpcPlatform;
break;
}
}
ASSERT(platform);
2001-05-25 20:43:47 +02:00
platform->setThingSubType( Type );
2001-05-25 22:00:13 +02:00
platform->setTiltable( false );
2001-04-25 00:05:29 +02:00
2001-05-25 22:00:13 +02:00
return( platform );
}
2001-04-25 00:05:29 +02:00
2001-05-25 22:00:13 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CNpcPlatform *CNpcPlatform::Create(sThingPlatform *ThisPlatform)
{
CNpcPlatform *platform;
NPC_PLATFORM_UNIT_TYPE Type = getTypeFromMapEdit( ThisPlatform->Type );
platform=Create(Type);
switch( Type )
{
case NPC_DUAL_PLATFORM:
{
CNpcDualPlatform *dualPlatformMaster = (CNpcDualPlatform *) platform;
dualPlatformMaster->setMaster( true );
CNpcDualPlatform *dualPlatformSlave;
dualPlatformSlave = (CNpcDualPlatform *) CNpcPlatform::Create( NPC_DUAL_PLATFORM );
dualPlatformSlave->setMaster( false );
2001-05-29 20:40:38 +02:00
dualPlatformSlave->setThingSubType( Type );
2001-05-25 22:00:13 +02:00
dualPlatformSlave->setGraphic( ThisPlatform );
dualPlatformSlave->setTiltable( false );
dualPlatformMaster->setOtherPlatform( dualPlatformSlave );
dualPlatformSlave->setOtherPlatform( dualPlatformMaster );
break;
}
default:
break;
}
ASSERT(platform);
platform->setGraphic( ThisPlatform );
platform->setWaypoints( ThisPlatform );
2001-04-25 00:05:29 +02:00
return( platform );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::setWaypoints( sThingPlatform *ThisPlatform )
{
int pointNum;
2001-04-23 22:40:13 +02:00
u16 *PntList=(u16*)MakePtr(ThisPlatform,sizeof(sThingPlatform));
2001-05-30 00:07:28 +02:00
u16 *waypoints;
2001-04-23 22:40:13 +02:00
u16 newXPos, newYPos;
newXPos = (u16) *PntList;
2001-05-30 00:07:28 +02:00
waypoints = PntList;
2001-04-23 22:40:13 +02:00
PntList++;
newYPos = (u16) *PntList;
PntList++;
DVECTOR startPos;
2001-05-31 18:24:48 +02:00
startPos.vx = ( newXPos << 4 ) + 8;
startPos.vy = ( newYPos << 4 ) + 16;
2001-04-23 22:40:13 +02:00
2001-04-25 00:05:29 +02:00
init( startPos );
2001-04-23 22:40:13 +02:00
2001-05-30 00:07:28 +02:00
setWaypointCount( ThisPlatform->PointCount - 1 );
2001-04-23 22:40:13 +02:00
2001-05-30 00:07:28 +02:00
setWaypointPtr( waypoints );
2001-06-19 22:07:57 +02:00
s32 minX, maxX, minY, maxY;
m_npcPath.getPathXExtents( &minX, &maxX );
m_npcPath.getPathYExtents( &minY, &maxY );
m_thinkArea.x1 = minX;
m_thinkArea.x2 = maxX;
m_thinkArea.y1 = minY;
m_thinkArea.y2 = maxY;
2001-04-25 00:05:29 +02:00
}
2001-04-23 22:40:13 +02:00
2001-04-25 00:05:29 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::setGraphic( sThingPlatform *ThisPlatform )
{
2001-05-03 21:01:59 +02:00
m_graphicNum = ThisPlatform->Gfx;
2001-04-25 00:05:29 +02:00
m_modelGfx = new ("ModelGfx") CModelGfx;
2001-05-03 21:01:59 +02:00
m_modelGfx->SetModel( m_graphicNum );
2001-04-23 22:40:13 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-27 13:52:40 +02:00
void CNpcPlatform::setGraphic( u8 graphicNum )
{
2001-05-03 21:01:59 +02:00
m_graphicNum = graphicNum;
2001-04-27 13:52:40 +02:00
m_modelGfx = new ("ModelGfx") CModelGfx;
m_modelGfx->SetModel( graphicNum );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 17:27:50 +02:00
void CNpcPlatform::init()
{
CPlatformThing::init();
2001-05-29 20:40:38 +02:00
m_dataPtr=&m_data[getThingSubType()];
2001-04-27 13:52:40 +02:00
2001-04-23 17:27:50 +02:00
m_heading = 0;
m_velocity = 0;
m_rotation = 0;
m_reversed = false;
m_extension = 0;
m_contact = false;
2001-05-29 20:40:38 +02:00
m_timer = m_dataPtr->initTimer * GameState::getOneSecondInFrames();
m_timerType = m_dataPtr->initTimerType;
2001-04-23 17:27:50 +02:00
m_isActive = true;
2001-05-29 20:40:38 +02:00
m_detectCollision = m_dataPtr->detectCollision;
2001-04-23 17:27:50 +02:00
m_state = 0;
m_tiltAngle = 0;
m_tiltVelocity = 0;
m_tiltable = false;
2001-05-23 16:46:23 +02:00
m_initRotation = 0;
2001-04-23 17:27:50 +02:00
m_lifetime = 0;
2001-05-29 20:40:38 +02:00
m_lifetimeType = m_dataPtr->lifetimeType;
2001-04-23 17:27:50 +02:00
m_npcPath.initPath();
2001-05-09 23:27:23 +02:00
2001-05-29 20:40:38 +02:00
m_speed = m_dataPtr->speed;
2001-06-18 21:06:43 +02:00
m_soundId = (int) NOT_PLAYING;
2001-04-23 17:27:50 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::init( DVECTOR initPos )
{
init();
Pos = m_initPos = m_base = initPos;
2001-05-29 20:40:38 +02:00
m_initLifetime = m_lifetime = GameState::getOneSecondInFrames() * m_dataPtr->lifetime;
2001-04-23 17:27:50 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::init( DVECTOR initPos, s32 initLifetime )
{
init( initPos );
m_initLifetime = m_lifetime = GameState::getOneSecondInFrames() * initLifetime;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::reinit()
{
m_heading = 0;
m_velocity = 0;
m_rotation = 0;
m_reversed = false;
m_contact = false;
2001-05-29 20:40:38 +02:00
m_timer = m_dataPtr->initTimer * GameState::getOneSecondInFrames();
m_timerType = m_dataPtr->initTimerType;
2001-04-23 17:27:50 +02:00
m_isActive = true;
2001-05-29 20:40:38 +02:00
m_detectCollision = m_dataPtr->detectCollision;
2001-04-23 17:27:50 +02:00
m_state = 0;
m_tiltAngle = 0;
m_tiltVelocity = 0;
m_lifetime = m_initLifetime;
2001-04-23 22:40:13 +02:00
Pos = m_initPos;
}
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 17:27:50 +02:00
2001-05-23 16:46:23 +02:00
void CNpcPlatform::calculateNonRotatedCollisionData()
2001-04-23 22:40:13 +02:00
{
2001-05-23 16:46:23 +02:00
DVECTOR collisionSize = getCollisionSize();
DVECTOR collisionOffset = getCollisionCentreOffset();
2001-05-05 21:08:02 +02:00
2001-05-23 16:46:23 +02:00
m_nonRotatedCollisionArea.XMax = ( collisionSize.vx >> 1 ) + collisionOffset.vx;
m_nonRotatedCollisionArea.XMin = -( collisionSize.vx >> 1 ) + collisionOffset.vx;
m_nonRotatedCollisionArea.YMax = ( collisionSize.vy >> 1 ) + collisionOffset.vy;
m_nonRotatedCollisionArea.YMin = -( collisionSize.vy >> 1 ) + collisionOffset.vy;
2001-05-09 16:34:08 +02:00
2001-05-23 16:46:23 +02:00
m_nonRotatedCollisionOffset = collisionOffset;
}
2001-05-09 16:34:08 +02:00
2001-05-23 16:46:23 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-05-09 16:34:08 +02:00
2001-05-23 16:46:23 +02:00
void CNpcPlatform::postInit()
{
sBBox boundingBox = m_modelGfx->GetBBox();
setCollisionSize( ( boundingBox.XMax - boundingBox.XMin ), ( boundingBox.YMax - boundingBox.YMin ) );
setCollisionCentreOffset( ( boundingBox.XMax + boundingBox.XMin ) >> 1, ( boundingBox.YMax + boundingBox.YMin ) >> 1 );
2001-05-09 16:34:08 +02:00
2001-05-23 16:46:23 +02:00
calculateNonRotatedCollisionData();
setCollisionAngle( m_tiltAngle >> 8 );
2001-04-23 17:27:50 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::shutdown()
{
2001-06-18 21:06:43 +02:00
if ( m_soundId != NOT_PLAYING )
{
CSoundMediator::stopAndUnlockSfx( (xmPlayingId) m_soundId );
}
2001-04-23 17:27:50 +02:00
delete m_modelGfx;
// temporary
CPlatformThing::shutdown();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-06-18 21:06:43 +02:00
void CNpcPlatform::leftThinkZone(int _frames)
{
if ( m_soundId != NOT_PLAYING )
{
CSoundMediator::stopAndUnlockSfx( (xmPlayingId) m_soundId );
m_soundId = NOT_PLAYING;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 22:40:13 +02:00
void CNpcPlatform::processLifetime( int _frames )
2001-04-23 17:27:50 +02:00
{
2001-04-23 22:40:13 +02:00
switch( m_lifetimeType )
2001-04-23 17:27:50 +02:00
{
2001-04-23 22:40:13 +02:00
case NPC_PLATFORM_FINITE_LIFE:
2001-04-23 17:27:50 +02:00
{
2001-04-23 22:40:13 +02:00
m_lifetime -= _frames;
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
if ( m_lifetime <= 0 )
2001-04-23 17:27:50 +02:00
{
2001-04-25 22:09:36 +02:00
setToShutdown();
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
return;
}
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
break;
}
case NPC_PLATFORM_FINITE_LIFE_RESPAWN:
{
m_lifetime -= _frames;
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
if ( m_lifetime <= 0 )
{
reinit();
2001-04-23 17:27:50 +02:00
}
2001-04-23 22:40:13 +02:00
break;
}
case NPC_PLATFORM_INFINITE_LIFE_COLLAPSIBLE:
{
if ( m_contact )
2001-04-23 17:27:50 +02:00
{
m_lifetime -= _frames;
if ( m_lifetime <= 0 )
{
2001-04-23 22:40:13 +02:00
m_isActive = false;
m_timer = 3 * GameState::getOneSecondInFrames();
m_timerType = NPC_PLATFORM_TIMER_RESPAWN;
2001-04-23 17:27:50 +02:00
}
}
2001-04-23 22:40:13 +02:00
break;
}
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
default:
break;
}
}
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 17:27:50 +02:00
2001-04-23 22:40:13 +02:00
void CNpcPlatform::think(int _frames)
{
2001-06-18 21:06:43 +02:00
if ( m_soundId != NOT_PLAYING )
{
if( !CSoundMediator::isSfxStillPlaying( (xmPlayingId) m_soundId ) )
{
// unlock sound if it has finished
CSoundMediator::stopAndUnlockSfx( (xmPlayingId) m_soundId );
m_soundId = NOT_PLAYING;
}
}
2001-04-27 13:52:40 +02:00
2001-04-23 22:40:13 +02:00
if ( m_isActive )
{
if ( m_tiltable )
{
processTilt( _frames );
2001-04-23 17:27:50 +02:00
}
2001-04-23 22:40:13 +02:00
processLifetime( _frames );
2001-04-23 17:27:50 +02:00
if ( m_heading > 1024 && m_heading < 3072 )
{
m_reversed = true;
}
else
{
m_reversed = false;
}
2001-04-25 17:48:31 +02:00
int moveFrames = _frames;
if ( moveFrames > 2 )
{
// make sure platforms don't go berserk if too many frames are dropped
moveFrames = 2;
}
processMovement( moveFrames );
2001-04-23 17:27:50 +02:00
m_contact = false;
}
processTimer( _frames );
CPlatformThing::think(_frames);
}
2001-04-27 22:13:09 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::setCollisionAngle(int newAngle)
{
2001-05-25 20:43:47 +02:00
m_collisionAngle=newAngle;
// CPlatformThing::setCollisionAngle(newAngle);
2001-05-21 16:22:26 +02:00
calculateBoundingBoxSize();
2001-05-25 21:08:35 +02:00
2001-04-27 22:13:09 +02:00
CPlayer *player;
// Is the player stood on this platform as it rotates?
player=GameScene.getPlayer();
if(player->isOnPlatform()==this)
{
DVECTOR playerPos;
playerPos=player->getPos();
2001-05-21 16:22:26 +02:00
DVECTOR shove;
shove.vx = 0;
shove.vy = getHeightFromPlatformAtPosition( playerPos.vx, playerPos.vy );
player->shove(shove);
2001-04-27 22:13:09 +02:00
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::calculateBoundingBoxSize()
{
2001-05-23 16:46:23 +02:00
sBBox boundingBox = m_nonRotatedCollisionArea;
2001-05-21 16:22:26 +02:00
// 'render' collision box at correct angle
SVECTOR testPointsNonRel[4];
VECTOR testPoints[4];
testPointsNonRel[0].vx = boundingBox.XMin;
testPointsNonRel[0].vy = boundingBox.YMin;
testPointsNonRel[1].vx = boundingBox.XMax;
testPointsNonRel[1].vy = boundingBox.YMin;
testPointsNonRel[2].vx = boundingBox.XMax;
testPointsNonRel[2].vy = boundingBox.YMax;
testPointsNonRel[3].vx = boundingBox.XMin;
testPointsNonRel[3].vy = boundingBox.YMax;
MATRIX mtx;
SetIdentNoTrans(&mtx );
2001-05-23 16:46:23 +02:00
RotMatrixZ( getCollisionAngle() + m_initRotation, &mtx );
2001-05-21 16:22:26 +02:00
int i;
for ( i = 0 ; i < 4 ; i++ )
{
ApplyMatrix( &mtx, &testPointsNonRel[i], &testPoints[i] );
}
2001-05-23 16:46:23 +02:00
SVECTOR offsetSource;
VECTOR offsetTarget;
offsetSource.vx = m_nonRotatedCollisionOffset.vx;
offsetSource.vy = m_nonRotatedCollisionOffset.vy;
ApplyMatrix( &mtx, &offsetSource, &offsetTarget );
2001-05-21 16:22:26 +02:00
int x1, x2, y1, y2;
x1 = x2 = testPoints[0].vx;
y1 = y2 = testPoints[0].vy;
for ( i = 1 ; i < 4 ; i++ )
{
if ( testPoints[i].vy < y1 )
{
y1 = testPoints[i].vy;
}
else if ( testPoints[i].vy > y2 )
{
y2 = testPoints[i].vy;
}
if ( testPoints[i].vx < x1 )
{
x1 = testPoints[i].vx;
}
else if ( testPoints[i].vx > x2 )
{
x2 = testPoints[i].vx;
}
}
setCollisionSize( x2 - x1 + 1, y2 - y1 + 1 );
2001-05-23 16:46:23 +02:00
setCollisionCentreOffset( offsetTarget.vx, offsetTarget.vy );
2001-04-27 22:13:09 +02:00
}
2001-04-23 17:27:50 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::processTilt( int _frames )
{
bool forceActing = false;
if ( m_contact )
{
// user is touching platform, tilt accordingly
CPlayer *player = GameScene.getPlayer();
DVECTOR playerPos = player->getPos();
if ( playerPos.vx > Pos.vx + 10 )
{
forceActing = true;
// tilt clockwise
if ( m_tiltVelocity < 2560 )
{
m_tiltVelocity += 64;
}
}
else if ( playerPos.vx < Pos.vx - 10 )
{
forceActing = true;
// tilt anticlockwise
if ( m_tiltVelocity > -2560 )
{
m_tiltVelocity -= 64;
}
}
}
if ( !forceActing )
{
// no force acting, hence reduce velocity
s32 reduction = abs( m_tiltVelocity );
if ( reduction > 64 )
{
reduction = 64;
}
if ( m_tiltVelocity >= 0 )
{
reduction *= -1;
}
m_tiltVelocity += reduction;
}
m_tiltAngle += m_tiltVelocity;
if ( m_tiltAngle > ( 512 << 8 ) )
{
m_tiltAngle = ( 512 << 8 );
m_tiltVelocity = 0;
}
else if ( m_tiltAngle < -( 512 << 8 ) )
{
m_tiltAngle = -( 512 << 8 );
m_tiltVelocity = 0;
}
setCollisionAngle( m_tiltAngle >> 8 );
/*if ( getCollisionAngle() > 512 && getCollisionAngle() < 3584 )
{
m_detectCollision = false;
}
else
{
m_detectCollision = true;
}*/
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::processTimer( int _frames )
{
switch( m_timerType )
{
case NPC_PLATFORM_TIMER_NONE:
break;
case NPC_PLATFORM_TIMER_RESPAWN:
{
if ( m_timer > 0 )
{
m_timer -= _frames;
}
else
{
reinit();
}
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-05-21 16:22:26 +02:00
u8 CNpcPlatform::checkCollisionDelta( CThing *_thisThing, int threshold, CRECT collisionArea )
{
// check for case of "was not colliding previously because was above" +
// "is not colliding now because is below"
DVECTOR otherPos = _thisThing->getPos();
if ( getHeightFromPlatformAtPosition( otherPos.vx, otherPos.vy ) < 0 )
{
// is currently below platform landing point
DVECTOR otherPosDelta = _thisThing->getPosDelta();
DVECTOR posDelta = getPosDelta();
if ( otherPosDelta.vy > 0 || posDelta.vy < 0 )
{
// object is dropping vertically, or platform is rising vertically
// get both object's previous positions
s32 oldXPos = otherPos.vx - otherPosDelta.vx;
s32 oldYPos = otherPos.vy - otherPosDelta.vy;
2001-07-12 16:10:26 +02:00
CRECT otherCollisionArea = _thisThing->getCollisionArea();
otherCollisionArea.x1 -= otherPosDelta.vx;
otherCollisionArea.x2 -= otherPosDelta.vx;
otherCollisionArea.y1 -= otherPosDelta.vy;
otherCollisionArea.y2 -= otherPosDelta.vy;
2001-05-21 16:22:26 +02:00
collisionArea.x1 -= posDelta.vx;
collisionArea.x2 -= posDelta.vx;
collisionArea.y1 -= posDelta.vy;
s32 oldCollisionY = collisionArea.y2;
collisionArea.y2 -= posDelta.vy;
2001-07-12 16:10:26 +02:00
//if ( oldXPos >= collisionArea.x1 && oldXPos <= collisionArea.x2 )
if ( otherCollisionArea.x2 >= collisionArea.x1 && otherCollisionArea.x1 <= collisionArea.x2 )
2001-05-21 16:22:26 +02:00
{
//if ( oldYPos < collisionArea.y1 + threshold ) //&& otherPos.vy > oldCollisionY )
if ( getHeightFromPlatformAtPosition( oldXPos, oldYPos, -posDelta.vx, -posDelta.vy ) > 0 )
{
// if object's old position was above old platform collision area,
// but is now below current platform collision area, we can assume
// the player has hit the platform in the intervening time
return( true );
}
}
}
}
return( false );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 17:27:50 +02:00
void CNpcPlatform::collidedWith( CThing *_thisThing )
{
switch(_thisThing->getThingType())
{
case TYPE_PLAYER:
{
2001-05-21 18:28:10 +02:00
CPlayer *player;
DVECTOR playerPos;
CRECT collisionArea;
2001-07-12 16:10:26 +02:00
CRECT playerCollisionArea;
2001-05-21 18:28:10 +02:00
// Only interested in SBs feet colliding with the box (pkg)
player=(CPlayer*)_thisThing;
playerPos=player->getPos();
2001-07-12 16:10:26 +02:00
playerCollisionArea = player->getCollisionArea();
2001-05-21 18:28:10 +02:00
collisionArea=getCollisionArea();
2001-04-27 04:05:05 +02:00
2001-05-21 18:28:10 +02:00
s32 threshold = abs( collisionArea.y2 - collisionArea.y1 );
2001-05-21 16:22:26 +02:00
2001-05-21 18:28:10 +02:00
if ( threshold > 16 )
{
threshold = 16;
}
2001-05-21 16:22:26 +02:00
2001-07-12 16:10:26 +02:00
//if( playerPos.vx >= collisionArea.x1 && playerPos.vx <= collisionArea.x2 )
if( playerCollisionArea.x2 >= collisionArea.x1 && playerCollisionArea.x1 <= collisionArea.x2 )
2001-05-21 18:28:10 +02:00
{
if ( checkCollisionDelta( _thisThing, threshold, collisionArea ) )
2001-04-23 17:27:50 +02:00
{
2001-05-21 18:28:10 +02:00
player->setPlatform( this );
2001-04-23 17:27:50 +02:00
2001-05-21 18:28:10 +02:00
m_contact = true;
}
else
2001-05-21 16:22:26 +02:00
{
2001-05-21 18:28:10 +02:00
if( playerPos.vy >= collisionArea.y1 && playerPos.vy <= collisionArea.y2 )
2001-05-01 21:36:24 +02:00
{
2001-05-21 18:28:10 +02:00
int height = getHeightFromPlatformAtPosition( playerPos.vx, playerPos.vy );
2001-05-21 16:22:26 +02:00
2001-05-21 18:28:10 +02:00
if ( height >= -threshold && height < 1 )
2001-05-21 16:22:26 +02:00
{
2001-05-21 18:28:10 +02:00
player->setPlatform( this );
2001-05-21 16:22:26 +02:00
2001-05-21 18:28:10 +02:00
m_contact = true;
2001-05-21 16:22:26 +02:00
}
}
2001-04-23 17:27:50 +02:00
}
}
break;
}
2001-05-25 21:08:35 +02:00
case TYPE_NPC:
2001-05-05 21:08:02 +02:00
{
2001-05-25 21:08:35 +02:00
CNpcFriend *friendNpc;
DVECTOR friendPos;
CRECT collisionArea;
friendNpc = (CNpcFriend*) _thisThing;
friendPos = friendNpc->getPos();
collisionArea=getCollisionArea();
s32 threshold = abs( collisionArea.y2 - collisionArea.y1 );
2001-05-05 21:08:02 +02:00
2001-05-25 21:08:35 +02:00
if ( threshold > 16 )
{
threshold = 16;
}
2001-05-08 18:25:45 +02:00
2001-05-25 21:08:35 +02:00
if( friendPos.vx >= collisionArea.x1 && friendPos.vx <= collisionArea.x2 )
{
if ( checkCollisionDelta( _thisThing, threshold, collisionArea ) )
{
int height = getHeightFromPlatformAtPosition( friendPos.vx, friendPos.vy );
2001-05-08 18:25:45 +02:00
2001-05-25 21:08:35 +02:00
friendNpc->setPlatform( this );
m_contact = true;
}
else
{
if( friendPos.vy >= collisionArea.y1 && friendPos.vy <= collisionArea.y2 )
{
int height = getHeightFromPlatformAtPosition( friendPos.vx, friendPos.vy );
if ( height >= -threshold && height < 1 )
{
friendNpc->setPlatform( this );
m_contact = true;
}
}
}
}
2001-05-08 18:25:45 +02:00
2001-05-05 21:08:02 +02:00
break;
}
2001-05-25 21:08:35 +02:00
case TYPE_HAZARD:
break;
2001-04-23 17:27:50 +02:00
default:
ASSERT(0);
break;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 22:40:13 +02:00
void CNpcPlatform::processMovement( int _frames )
2001-04-23 17:27:50 +02:00
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::render()
{
if ( m_isActive )
{
CPlatformThing::render();
// Render
2001-05-10 18:16:57 +02:00
if (canRender())
2001-04-23 17:27:50 +02:00
{
2001-05-10 18:16:57 +02:00
DVECTOR &renderPos=getRenderPos();
m_modelGfx->Render(renderPos);
2001-05-10 18:47:35 +02:00
}
2001-04-23 17:27:50 +02:00
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-05-21 16:22:26 +02:00
int CNpcPlatform::checkCollisionAgainst(CThing *_thisThing, int _frames)
2001-04-23 17:27:50 +02:00
{
2001-05-23 23:27:29 +02:00
switch(_thisThing->getThingType())
2001-05-21 18:28:10 +02:00
{
2001-05-23 23:27:29 +02:00
case TYPE_PLAYERPROJECTILE:
return( false );
default:
{
int collided = false;
2001-04-23 17:27:50 +02:00
2001-05-23 23:27:29 +02:00
if ( m_detectCollision && m_isActive && !isSetToShutdown() )
{
CRECT thisRect, thatRect;
2001-04-23 17:27:50 +02:00
2001-05-23 23:27:29 +02:00
thisRect = getCollisionArea();
thatRect = _thisThing->getCollisionArea();
2001-04-23 17:27:50 +02:00
2001-05-23 23:27:29 +02:00
DVECTOR posDelta = getPosDelta();
2001-04-23 17:27:50 +02:00
2001-05-23 23:27:29 +02:00
thisRect.y1 -= abs( posDelta.vy ) >> 1;
thisRect.y2 += abs( posDelta.vy ) >> 1;
2001-04-23 17:27:50 +02:00
2001-05-23 23:27:29 +02:00
posDelta = _thisThing->getPosDelta();
2001-04-23 17:27:50 +02:00
2001-05-23 23:27:29 +02:00
thatRect.y1 -= abs( posDelta.vy ) >> 1;
thatRect.y2 += abs( posDelta.vy ) >> 1;
if(((thisRect.x1>=thatRect.x1&&thisRect.x1<=thatRect.x2)||(thisRect.x2>=thatRect.x1&&thisRect.x2<=thatRect.x2)||(thisRect.x1<=thatRect.x1&&thisRect.x2>=thatRect.x2))&&
((thisRect.y1>=thatRect.y1&&thisRect.y1<=thatRect.y2)||(thisRect.y2>=thatRect.y1&&thisRect.y2<=thatRect.y2)||(thisRect.y1<=thatRect.y1&&thisRect.y2>=thatRect.y2)))
{
collided = true;
}
}
return( collided );
2001-05-21 18:28:10 +02:00
}
2001-04-23 17:27:50 +02:00
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::setTiltable( bool isTiltable )
{
m_tiltable = isTiltable;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-05-21 16:22:26 +02:00
int CNpcPlatform::getHeightFromPlatformAtPosition(int _x,int _y, int offsetX, int offsetY)
2001-04-27 04:05:05 +02:00
{
2001-05-21 16:22:26 +02:00
DVECTOR top;
2001-05-17 18:24:28 +02:00
int angle;
2001-04-27 04:05:05 +02:00
2001-05-21 16:22:26 +02:00
CRECT collisionArea = getCollisionArea();
2001-05-21 23:57:28 +02:00
top.vy = offsetY + collisionArea.y1;
2001-05-21 16:22:26 +02:00
2001-05-23 16:46:23 +02:00
angle=getCollisionAngle() + m_initRotation;
2001-05-17 18:24:28 +02:00
if(angle==0)
{
// Non-rotated platform
2001-05-21 23:57:28 +02:00
2001-05-21 16:22:26 +02:00
return( top.vy - _y );
2001-05-17 18:24:28 +02:00
}
else
{
2001-05-21 23:57:28 +02:00
if ( angle > 0 )
{
top.vx = offsetX + collisionArea.x1;
}
else
{
top.vx = offsetX + collisionArea.x2;
}
2001-07-12 16:10:26 +02:00
if ( _x > collisionArea.x2 )
{
_x = collisionArea.x2;
}
else if ( _x < collisionArea.x1 )
{
_x = collisionArea.x1;
}
2001-05-17 18:24:28 +02:00
// Rotate backwards to find height at current position
2001-05-21 16:22:26 +02:00
2001-05-24 01:16:43 +02:00
s16 cosVal = rcos( angle );
2001-05-21 16:22:26 +02:00
2001-05-24 01:16:43 +02:00
if ( !cosVal )
{
return( top.vy - _y );
}
else
{
int hypotenuse = ( ( top.vx - _x ) << 12 ) / cosVal;
int angleHeight = -( hypotenuse * rsin( angle ) ) >> 12;
2001-05-21 16:22:26 +02:00
2001-05-24 01:16:43 +02:00
return( ( top.vy - _y ) + angleHeight );
}
2001-05-17 18:24:28 +02:00
}
2001-04-27 04:05:05 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-05-30 00:07:28 +02:00
/*void CNpcPlatform::addWaypoint( u16 *ptr )
2001-04-23 17:27:50 +02:00
{
2001-05-30 00:07:28 +02:00
m_npcPath.addWaypoint( ptr );
}
2001-04-23 17:27:50 +02:00
2001-05-30 00:07:28 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001-04-23 17:27:50 +02:00
2001-05-30 00:07:28 +02:00
void CNpcPlatform::addWaypoint( u16 *ptrX, u16 *ptrY )
{
m_npcPath.addWaypoint( ptrX, ptrY );
}*/
2001-04-23 17:27:50 +02:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CNpcPlatform::setTypeFromMapEdit( u16 newType )
{
2001-05-29 20:40:38 +02:00
int Type= mapEditConvertTable[newType];
setThingSubType(Type);
2001-04-23 22:40:13 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CNpcPlatform::NPC_PLATFORM_UNIT_TYPE CNpcPlatform::getTypeFromMapEdit( u16 newType )
{
return( mapEditConvertTable[newType] );
2001-07-16 22:50:07 +02:00
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CNpcPlatform::alwaysThink()
{
int chapter=GameScene.getChapterNumber();
int level=GameScene.getLevelNumber();
return( chapter == 1 && level == 5 );
}