mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-13 15:40:57 +00:00
718 lines
23 KiB
C++
718 lines
23 KiB
C++
/* ResidualVM - A 3D game interpreter
|
|
*
|
|
* ResidualVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the AUTHORS
|
|
* file distributed with this source distribution.
|
|
*
|
|
* Additional copyright for this file:
|
|
* Copyright (C) 1999-2000 Revolution Software Ltd.
|
|
* This code is based on source code created by Revolution Software,
|
|
* used with permission.
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "engines/icb/p4.h" //for machine version
|
|
#include "engines/icb/common/px_common.h"
|
|
#include "engines/icb/common/px_linkeddatafile.h"
|
|
#include "engines/icb/player.h"
|
|
#include "engines/icb/direct_input.h"
|
|
#include "engines/icb/common/px_route_barriers.h"
|
|
#include "engines/icb/global_objects.h"
|
|
#include "engines/icb/common/px_scriptengine.h"
|
|
#include "engines/icb/mission.h"
|
|
#include "engines/icb/global_switches.h"
|
|
|
|
namespace ICB {
|
|
|
|
#define FACING_FORWARDS ((70 * 4096) / 360)
|
|
#define FACING_BACKWARDS ((135 * 4096) / 360)
|
|
|
|
#define STOOD_TURN_TOLERANCE ((10 * 4096) / 360)
|
|
#define WALK_TURN_TOLERANCE ((20 * 4096) / 360)
|
|
#define STAIR_TURN_TOLERANCE ((130 * 4096) / 360)
|
|
#define STOOD_HARD_TURN_TOLERANCE ((60 * 4096) / 360)
|
|
#define NO_TURN_TOLERANCE (2 * 4096)
|
|
#define RUN_TURN_TOLERANCE ((30 * 4096) / 360)
|
|
|
|
#define NEAREST_INT(X) (X) > 0.0 ? int((X) + 0.5) : int((X)-0.5)
|
|
#define FIXED_POINT_ANG(X) NEAREST_INT(((X)*4096.0f) / (2 * M_PI))
|
|
|
|
#define SECOND_ZONE 80
|
|
|
|
#define R_LIMIT 50
|
|
|
|
#define CHECKDXDY(dx, dy) \
|
|
{ \
|
|
int r2 = (dx) * (dx) + (dy) * (dy); \
|
|
if (r2 < R_LIMIT * R_LIMIT) { \
|
|
if (r2 < 1) \
|
|
r2 = 1; \
|
|
int scale = NEAREST_INT(PXsqrt((double)(128 * 128 * R_LIMIT * R_LIMIT) / r2)); \
|
|
(dx) = ((dx)*scale) / 128; \
|
|
(dy) = ((dy)*scale) / 128; \
|
|
} \
|
|
}
|
|
|
|
// Which pan value the joystick is pointing at
|
|
uint32 g_targetPan = 0;
|
|
int g_playerPan;
|
|
int g_joyPan;
|
|
|
|
uint8 _DRAWCOMPASS_ = 0;
|
|
|
|
// pc device switch
|
|
__pc_input device = __KEYS; // default to keys
|
|
|
|
uint32 fire_key;
|
|
uint32 interact_key;
|
|
uint32 inventory_key;
|
|
uint32 arm_key;
|
|
uint32 remora_key;
|
|
uint32 crouch_key;
|
|
uint32 sidestep_key;
|
|
uint32 run_key;
|
|
uint32 up_key;
|
|
uint32 down_key;
|
|
uint32 left_key;
|
|
uint32 right_key;
|
|
uint32 pause_key;
|
|
|
|
void _player::Update_input_state() {
|
|
// looks at the input devices in use and returns a single user-is-doing state
|
|
|
|
// note - analogue controllers return a direction which is different from forward-and-rotate schemes
|
|
|
|
// this routine requires seperate pc/psx coding
|
|
|
|
// pc devices
|
|
// ----------
|
|
// keys
|
|
// joysticks
|
|
// gamepads
|
|
// analogue devices
|
|
|
|
// Are we trying to find a new pan value
|
|
static uint32 hunting = 0;
|
|
g_targetPan = 0;
|
|
g_playerPan = NEAREST_INT(log->pan * 4096.0f);
|
|
int screenPan = 0;
|
|
int clastCameraPan = NEAREST_INT(lastCameraPan * 4096.0f);
|
|
int cdeltaCameraPan = NEAREST_INT(deltaCameraPan * 4096.0f);
|
|
|
|
int stairs = 0;
|
|
int ladders = 0;
|
|
|
|
int turn_tolerance = STOOD_TURN_TOLERANCE;
|
|
int hard_turn_tolerance = STOOD_HARD_TURN_TOLERANCE;
|
|
|
|
// Defaults
|
|
cur_state.turn = __NO_TURN;
|
|
cur_state.bitflag = 0;
|
|
|
|
// Make sure we have a set to use !
|
|
// Use lazy logic evaluation
|
|
int haveCamera_ = MS->set.OK();
|
|
|
|
Poll_direct_input();
|
|
|
|
// Button controls are universal for all control modes
|
|
|
|
if ((Read_DI_keys(fire_key)) || (Read_Joystick(fire_button))) // Attack
|
|
cur_state.SetButton(__ATTACK);
|
|
|
|
if ((Read_DI_keys(interact_key)) || (Read_Joystick(interact_button))) // Interact
|
|
cur_state.SetButton(__INTERACT);
|
|
|
|
if ((Read_DI_keys(inventory_key)) || (Read_Joystick(inventory_button))) // Inventory
|
|
cur_state.SetButton(__INVENTORY);
|
|
|
|
if ((Read_DI_keys(arm_key)) || (Read_Joystick(arm_button))) // Arm/unarm
|
|
cur_state.SetButton(__ARMUNARM);
|
|
|
|
if ((Read_DI_keys(remora_key)) || (Read_Joystick(remora_button))) // Remora
|
|
cur_state.SetButton(__REMORA);
|
|
|
|
if ((Read_DI_keys(crouch_key)) || (Read_Joystick(crouch_button))) // Crouch
|
|
cur_state.SetButton(__CROUCH);
|
|
|
|
if ((Read_DI_keys(sidestep_key)) || (Read_Joystick(sidestep_button))) // Sidestep
|
|
cur_state.SetButton(__SIDESTEP);
|
|
|
|
if ((Read_DI_keys(run_key)) || (Read_Joystick(run_button))) // Jog
|
|
cur_state.SetButton(__JOG);
|
|
|
|
// No control whilst sliding down a ladder !
|
|
if (player_status == SLIP_SLIDIN_AWAY)
|
|
return;
|
|
|
|
// No control whilst getting onto a ladder
|
|
if ((player_status == EASY_LINKING) && (stat_after_link == BEGIN_DOWN_LADDER)) {
|
|
cur_state.momentum = __STILL;
|
|
return;
|
|
}
|
|
|
|
// Have different turn tolerances & control method for being on or off stairs
|
|
if ((stat_after_link == ON_STAIRS) || (player_status == ON_STAIRS) || (stat_after_link == STOOD_ON_STAIRS) || (player_status == STOOD_ON_STAIRS) ||
|
|
(stat_after_link == REVERSE_ON_STAIRS) || (player_status == REVERSE_ON_STAIRS) || (stat_after_link == RUNNING_ON_STAIRS) || (player_status == RUNNING_ON_STAIRS)) {
|
|
stairs = 1;
|
|
}
|
|
|
|
// Have different bigger tolerances & control method for being on or off ladders
|
|
if (((player_status == EASY_LINKING) && ((stat_after_link == ON_LADDER) || (stat_after_link == SLIP_SLIDIN_AWAY) || (stat_after_link == LEAVE_LADDER) ||
|
|
(stat_after_link == BEGIN_DOWN_LADDER) || (stat_after_link == LEAVE_LADDER_BOTTOM))) ||
|
|
(player_status == ON_LADDER) || (player_status == SLIP_SLIDIN_AWAY) || (player_status == LEAVE_LADDER) || (player_status == BEGIN_DOWN_LADDER) ||
|
|
(player_status == LEAVE_LADDER_BOTTOM)) {
|
|
ladders = 1;
|
|
g_playerPan = NEAREST_INT(4096.0f * MS->stairs[stair_num].pan_ref);
|
|
}
|
|
|
|
if (currentJoystick != NO_JOYSTICK) {
|
|
// If we are in inventory or remora mode then we should accept input
|
|
// from the keyboard by default (force attached joystick to digital)
|
|
if ((player_status == REMORA) || (player_status == INVENTORY)) {
|
|
// This mode will accept keyboard and joystick
|
|
currentJoystick = DIGITAL_JOYSTICK;
|
|
} else {
|
|
// Set joystick type to whatever is attached
|
|
currentJoystick = attachedJoystick;
|
|
|
|
// Set control mode dependent on attached device
|
|
if (currentJoystick != ANALOGUE_JOYSTICK) {
|
|
// Force mode for digital control device
|
|
Set_control_mode(ACTOR_RELATIVE);
|
|
}
|
|
}
|
|
|
|
// Only allow SCREEN_RELATIVE control if we have an analogue device
|
|
if ((Get_control_mode() == SCREEN_RELATIVE) && (haveCamera_ == 1)) {
|
|
PXcamera &camera = MSS.GetCamera();
|
|
|
|
int32 cameraPan = camera.pan;
|
|
|
|
if ((cameraPan > 2048) || (cameraPan < -2048)) {
|
|
// Make it +/- HALF_TURN
|
|
if (cameraPan > 0)
|
|
cameraPan -= 4096;
|
|
else
|
|
cameraPan += 4096;
|
|
}
|
|
|
|
screenPan = cameraPan;
|
|
|
|
// Catch if the screen pan has never been set
|
|
if (clastCameraPan > 2 * 4096) {
|
|
screenPan = cameraPan;
|
|
cdeltaCameraPan = 0;
|
|
panCycle = 0;
|
|
clastCameraPan = cameraPan;
|
|
} else {
|
|
// Have we changed camera angles ?
|
|
if (clastCameraPan != cameraPan) {
|
|
// Compute the new deltaCameraPan
|
|
cdeltaCameraPan = cameraPan - screenPan;
|
|
// Make -2048 -> 2048
|
|
if (cdeltaCameraPan > 2048)
|
|
cdeltaCameraPan -= 4096;
|
|
else if (cdeltaCameraPan < -2048)
|
|
cdeltaCameraPan += 4096;
|
|
|
|
cdeltaCameraPan = cdeltaCameraPan / CAMERA_SMOOTH_CYCLES;
|
|
panCycle = 0;
|
|
}
|
|
|
|
if (panCycle < CAMERA_SMOOTH_CYCLES) {
|
|
screenPan += cdeltaCameraPan;
|
|
panCycle++;
|
|
} else {
|
|
screenPan = cameraPan;
|
|
}
|
|
}
|
|
|
|
// Read joystick values
|
|
int x = Read_Joystick(Y_AXIS);
|
|
int y = Read_Joystick(X_AXIS);
|
|
int padlr = (x * x) + (y * y);
|
|
|
|
// Set new direction to hunt for
|
|
if (padlr > 0) {
|
|
if (x == 0) {
|
|
g_joyPan = 1024;
|
|
} else {
|
|
// This works jes' fine
|
|
g_joyPan = NEAREST_INT((atan((float)y / (float)x) / TWO_PI) * 4096.0f);
|
|
}
|
|
|
|
if ((x < 0) && (y > 0))
|
|
g_joyPan += 2048;
|
|
if ((x <= 0) && (y <= 0))
|
|
g_joyPan += 2048;
|
|
|
|
// Directly down
|
|
if (g_joyPan == 0)
|
|
g_joyPan = 1;
|
|
|
|
// Hunted for pan = g_joyPan - screenPan
|
|
g_targetPan = g_joyPan - screenPan;
|
|
|
|
// Make 0-4096
|
|
g_targetPan = g_targetPan % 4096;
|
|
// Looking for a new pan value
|
|
hunting = 1;
|
|
} else {
|
|
// Within deadzone so reset all
|
|
hunting = 0;
|
|
g_joyPan = 0;
|
|
g_targetPan = g_playerPan;
|
|
cur_state.turn = __NO_TURN;
|
|
cur_state.momentum = __STILL;
|
|
}
|
|
|
|
// If running then always running
|
|
if (cur_state.IsButtonSet(__JOG)) {
|
|
if (player_status == STOOD)
|
|
cur_state.momentum = __FORWARD_1;
|
|
else
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else
|
|
// Sidestep can be used as a brake
|
|
if (cur_state.IsButtonSet(__SIDESTEP)) {
|
|
if (player_status != STOOD)
|
|
cur_state.momentum = __STILL;
|
|
}
|
|
|
|
if (hunting) {
|
|
// Correct to get 0-4096
|
|
if (g_playerPan < 0)
|
|
g_playerPan += 4096;
|
|
|
|
ASSERT1(((g_playerPan >= 0) && (g_playerPan <= 4096)), "Bad g_playerPan %d", g_playerPan);
|
|
|
|
// So we should have a g_targetPan the character is trying to turn to
|
|
int delta = g_targetPan - g_playerPan;
|
|
|
|
delta = delta % 4096;
|
|
|
|
if (delta > 2048)
|
|
delta -= 4096;
|
|
if (delta < -2048)
|
|
delta += 4096;
|
|
|
|
int absDelta = abs(delta);
|
|
|
|
// Has the run been pressed
|
|
if (cur_state.IsButtonSet(__JOG)) {
|
|
// Not hunting for a pan value anymore
|
|
hunting = 0;
|
|
|
|
if (stairs == 1) {
|
|
// No turning on stairs whilst running
|
|
turn_tolerance = NO_TURN_TOLERANCE;
|
|
// Run : go from stand -> walk -> run
|
|
if (absDelta < FACING_FORWARDS) {
|
|
if (player_status == STOOD_ON_STAIRS)
|
|
cur_state.momentum = __FORWARD_1;
|
|
else
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else {
|
|
// Turn LEFT or RIGHT you decide whilst running
|
|
if (delta > turn_tolerance)
|
|
cur_state.turn = __LEFT;
|
|
else if (delta < -turn_tolerance)
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
} else if (ladders == 1) {
|
|
// RUN on ladder means slide down it fireman style
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else {
|
|
turn_tolerance = RUN_TURN_TOLERANCE;
|
|
|
|
// Turn LEFT or RIGHT you decide whilst running
|
|
if (delta > turn_tolerance)
|
|
cur_state.turn = __LEFT;
|
|
else if (delta < -turn_tolerance)
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
} else if (cur_state.IsButtonSet(__SIDESTEP)) {
|
|
hunting = 0;
|
|
|
|
if (stairs == 1) {
|
|
// No turning on stairs whilst running
|
|
turn_tolerance = NO_TURN_TOLERANCE;
|
|
|
|
// Run : go from stand -> walk -> run
|
|
if (absDelta < FACING_FORWARDS) {
|
|
if (player_status == STOOD_ON_STAIRS)
|
|
cur_state.momentum = __FORWARD_1;
|
|
else
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else {
|
|
// Turn LEFT or RIGHT you decide whilst running
|
|
if (delta > turn_tolerance)
|
|
cur_state.turn = __LEFT;
|
|
else if (delta < -turn_tolerance)
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
} else if (ladders == 1) {
|
|
// RUN on ladder means slide down it fireman style
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else {
|
|
turn_tolerance = RUN_TURN_TOLERANCE;
|
|
|
|
// The back facing 90 degrees is step backwards
|
|
if (absDelta > FACING_BACKWARDS) {
|
|
cur_state.momentum = __BACKWARD_1;
|
|
}
|
|
// So just left or right based on sign
|
|
// This means sidestep left or right
|
|
else {
|
|
if (delta > 0)
|
|
cur_state.turn = __LEFT;
|
|
else
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
}
|
|
} else {
|
|
// Nope, normal screen relative movement
|
|
|
|
// Catch if not pressing run but running ! then start walking
|
|
if (cur_state.momentum == __FORWARD_2) {
|
|
cur_state.momentum = __FORWARD_1;
|
|
}
|
|
|
|
// Have different turn tolerances for standing and walking
|
|
if (stairs == 1) {
|
|
turn_tolerance = STAIR_TURN_TOLERANCE;
|
|
} else if (ladders == 1) {
|
|
// No turning on ladders
|
|
turn_tolerance = NO_TURN_TOLERANCE;
|
|
} else if (player_status == WALKING) {
|
|
turn_tolerance = WALK_TURN_TOLERANCE;
|
|
} else {
|
|
turn_tolerance = STOOD_TURN_TOLERANCE;
|
|
hard_turn_tolerance = STOOD_HARD_TURN_TOLERANCE;
|
|
}
|
|
|
|
// Get these checks dealt with first
|
|
if (ladders == 1) {
|
|
// Just need to test for going down the ladder i.e. BACKWARDS
|
|
if (absDelta > FACING_BACKWARDS) {
|
|
cur_state.momentum = __BACKWARD_1;
|
|
} else if (absDelta < FACING_FORWARDS) {
|
|
cur_state.momentum = __FORWARD_1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Turn LEFT or RIGHT you decide
|
|
if (delta > hard_turn_tolerance) {
|
|
cur_state.turn = __HARD_LEFT;
|
|
} else if (delta < -hard_turn_tolerance) {
|
|
cur_state.turn = __HARD_RIGHT;
|
|
} else if (delta > turn_tolerance) {
|
|
cur_state.turn = __LEFT;
|
|
} else if (delta < -turn_tolerance) {
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
// So at the right direction start walking
|
|
else {
|
|
if (ladders == 1) {
|
|
// Just need to test for going down the ladder i.e. BACKWARDS
|
|
if (absDelta > FACING_BACKWARDS) {
|
|
cur_state.momentum = __BACKWARD_1;
|
|
} else if (absDelta < FACING_FORWARDS) {
|
|
cur_state.momentum = __FORWARD_1;
|
|
}
|
|
} else if ((stairs == 0) || (absDelta < FACING_FORWARDS)) {
|
|
hunting = 0;
|
|
|
|
// Are past the dead zone
|
|
if (padlr > 0) {
|
|
// Walk
|
|
cur_state.momentum = __FORWARD_1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // if(hunting)
|
|
else if (ladders == 1) {
|
|
// RUN on ladder means slide down it fireman style
|
|
if (cur_state.IsButtonSet(__JOG)) {
|
|
cur_state.momentum = __FORWARD_2;
|
|
}
|
|
}
|
|
|
|
// Can only use HARD_LEFT & HARD_RIGHT when STOOD
|
|
if (player_status != STOOD) {
|
|
if (cur_state.turn == __HARD_LEFT)
|
|
cur_state.turn = __LEFT;
|
|
else if (cur_state.turn == __HARD_RIGHT)
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
} // Get_control_mode() == SCREEN_RELATIVE
|
|
|
|
if (Get_control_mode() == ACTOR_RELATIVE) {
|
|
// Don't need to draw this
|
|
_DRAWCOMPASS_ = 0;
|
|
|
|
// Two modes of actor relative, analogue and digital
|
|
if (currentJoystick == ANALOGUE_JOYSTICK) {
|
|
int x = Read_Joystick(X_AXIS);
|
|
int y = Read_Joystick(Y_AXIS);
|
|
int padlr = (x * x) + (y * y);
|
|
|
|
// If running then always running
|
|
if (cur_state.IsButtonSet(__JOG)) {
|
|
if (player_status == STOOD)
|
|
cur_state.momentum = __FORWARD_1;
|
|
else
|
|
cur_state.momentum = __FORWARD_2;
|
|
|
|
// Turn left/right whilst walking/running
|
|
if (padlr > SECOND_ZONE) {
|
|
if (x < 0)
|
|
cur_state.turn = __LEFT;
|
|
else
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
} else
|
|
// Are we out of the deadzone
|
|
if (padlr > 0) {
|
|
// We want to turn right
|
|
if (x > 0) {
|
|
// We want to turn right fast
|
|
if (x > SECOND_ZONE) {
|
|
// Only allowed to hard turn when stood still and not sidestepping
|
|
if ((cur_state.momentum == __STILL) && (!cur_state.IsButtonSet(__SIDESTEP))) {
|
|
// Also consider button restraints
|
|
if (cur_state.IsButtonSet(__ARMUNARM) || cur_state.IsButtonSet(__CROUCH))
|
|
cur_state.turn = __RIGHT;
|
|
else
|
|
cur_state.turn = __HARD_RIGHT;
|
|
} else
|
|
cur_state.turn = __RIGHT;
|
|
}
|
|
// Turn right
|
|
else
|
|
cur_state.turn = __RIGHT;
|
|
} else
|
|
// We want to turn left
|
|
if (x < 0) {
|
|
// We want to turn left fast
|
|
if (x < -SECOND_ZONE) {
|
|
// Only allowed to hard turn when stood still and not sidestepping
|
|
if ((cur_state.momentum == __STILL) && (!cur_state.IsButtonSet(__SIDESTEP))) {
|
|
// Also consider button restraints
|
|
if (cur_state.IsButtonSet(__ARMUNARM) || cur_state.IsButtonSet(__CROUCH))
|
|
cur_state.turn = __LEFT;
|
|
else
|
|
cur_state.turn = __HARD_LEFT;
|
|
} else
|
|
cur_state.turn = __LEFT;
|
|
}
|
|
// Turn left
|
|
else
|
|
cur_state.turn = __LEFT;
|
|
}
|
|
// Don't want to turn at all
|
|
else
|
|
cur_state.turn = __NO_TURN;
|
|
|
|
// We want move forward
|
|
if (y < 0) {
|
|
// Can't move forward with sidestep held (unless on stairs or ladders)
|
|
if (cur_state.IsButtonSet(__SIDESTEP) && stairs == 0 && ladders == 0) {
|
|
cur_state.momentum = __STILL;
|
|
} else
|
|
// We want to walk
|
|
cur_state.momentum = __FORWARD_1;
|
|
} else
|
|
// We want to move backwards
|
|
if (y > 0) {
|
|
cur_state.momentum = __BACKWARD_1;
|
|
}
|
|
// Don't want to move
|
|
else
|
|
cur_state.momentum = __STILL;
|
|
} else {
|
|
// Within deadzone so don't move or turn
|
|
cur_state.momentum = __STILL;
|
|
cur_state.turn = __NO_TURN;
|
|
}
|
|
} // End of Analogue actor relative controls
|
|
else {
|
|
// Digital actor relative controls (same as keys)
|
|
// If running then always running
|
|
if (cur_state.IsButtonSet(__JOG)) {
|
|
if (player_status == STOOD)
|
|
cur_state.momentum = __FORWARD_1;
|
|
else
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else
|
|
// Forward/backward - one or the other
|
|
if ((Read_DI_keys(up_key)) || (Read_Joystick(Y_AXIS) == JOY_UP)) {
|
|
// Can't move forward with sidestep held (unless on stairs or ladders)
|
|
if (cur_state.IsButtonSet(__SIDESTEP) && stairs == 0 && ladders == 0) {
|
|
cur_state.momentum = __STILL;
|
|
} else
|
|
// We want to walk
|
|
cur_state.momentum = __FORWARD_1;
|
|
} else if ((Read_DI_keys(down_key)) || (Read_Joystick(Y_AXIS) == JOY_DOWN))
|
|
cur_state.momentum = __BACKWARD_1;
|
|
else
|
|
cur_state.momentum = __STILL;
|
|
|
|
// Left/right
|
|
if ((Read_DI_keys(left_key)) || (Read_Joystick(X_AXIS) == JOY_LEFT)) {
|
|
cur_state.turn = __LEFT;
|
|
} else if ((Read_DI_keys(right_key)) || (Read_Joystick(X_AXIS) == JOY_RIGHT)) {
|
|
cur_state.turn = __RIGHT;
|
|
} else
|
|
cur_state.turn = __NO_TURN;
|
|
|
|
} // End of Digital actor relative control
|
|
}
|
|
|
|
}
|
|
// No Joystick
|
|
else {
|
|
// Keyboard support (generic controls)
|
|
|
|
// If running then always running
|
|
if (cur_state.IsButtonSet(__JOG)) {
|
|
if (player_status == STOOD)
|
|
cur_state.momentum = __FORWARD_1;
|
|
else
|
|
cur_state.momentum = __FORWARD_2;
|
|
} else
|
|
// Forward/backward - one or the other
|
|
if (Read_DI_keys(up_key)) {
|
|
// Can't move forward with sidestep held (unless on stairs or ladders)
|
|
if (cur_state.IsButtonSet(__SIDESTEP) && stairs == 0 && ladders == 0) {
|
|
cur_state.momentum = __STILL;
|
|
} else
|
|
// We want to walk
|
|
cur_state.momentum = __FORWARD_1;
|
|
} else if (Read_DI_keys(down_key))
|
|
cur_state.momentum = __BACKWARD_1;
|
|
else
|
|
cur_state.momentum = __STILL;
|
|
|
|
// Left/right
|
|
if (Read_DI_keys(left_key)) {
|
|
cur_state.turn = __LEFT;
|
|
} else if (Read_DI_keys(right_key)) {
|
|
cur_state.turn = __RIGHT;
|
|
} else
|
|
cur_state.turn = __NO_TURN;
|
|
}
|
|
|
|
// Set the floating point version of the fixed point variables we've used
|
|
lastCameraPan = ((float)clastCameraPan / 4096.0f);
|
|
deltaCameraPan = ((float)cdeltaCameraPan / 4096.0f);
|
|
}
|
|
|
|
void _player::DrawCompass() {
|
|
// User can disable joystick in which case mode is forced to actor
|
|
// relative and only the keys will work until the joystick is enabled
|
|
if (currentJoystick != NO_JOYSTICK) {
|
|
// Only draw compass in THREED mode and not while player is in inventory or remora mode
|
|
if ((px.display_mode == THREED) && (player_status != REMORA) && (player_status != INVENTORY) && _DRAWCOMPASS_) {
|
|
uint32 pitch;
|
|
uint8 *ad;
|
|
|
|
#define COMPASS_LENGTH 50.0f
|
|
#define COMPASS_OX 60
|
|
#define COMPASS_OY 420
|
|
|
|
_rgb purple = {250, 60, 200, 0};
|
|
_rgb turq = {0, 250, 250, 0};
|
|
_rgb yellow = {250, 250, 0, 0};
|
|
|
|
ad = surface_manager->Lock_surface(working_buffer_id);
|
|
pitch = surface_manager->Get_pitch(working_buffer_id);
|
|
|
|
if (g_joyPan == 0) {
|
|
// Centered/Within deadzone (display a cross)
|
|
General_draw_line_24_32(COMPASS_OX, COMPASS_OY - 5, COMPASS_OX, COMPASS_OY + 5, &yellow, ad, pitch);
|
|
General_draw_line_24_32(COMPASS_OX - 5, COMPASS_OY, COMPASS_OX + 5, COMPASS_OY, &yellow, ad, pitch);
|
|
} else {
|
|
float theta = ((float)g_joyPan / 4096.0f) * TWO_PI;
|
|
|
|
int x = NEAREST_INT(COMPASS_LENGTH * PXsin(theta));
|
|
int y = NEAREST_INT(COMPASS_LENGTH * PXcos(theta));
|
|
|
|
General_draw_line_24_32(COMPASS_OX, COMPASS_OY, (int16)(COMPASS_OX + x), (int16)(COMPASS_OY + y), &yellow, ad, pitch);
|
|
}
|
|
|
|
// Get the actor's screen position
|
|
PXvector origin_world, origin_scrn;
|
|
origin_world = log->mega->actor_xyz;
|
|
bool8 result;
|
|
PXcamera &camera = MSS.GetCamera();
|
|
PXWorldToFilm(origin_world, camera, result, origin_scrn);
|
|
|
|
PXvector point_world, point_scrn;
|
|
|
|
int dx, dy;
|
|
|
|
double s_ang, c_ang;
|
|
|
|
s_ang = PXsin(((float)g_targetPan / 4096.0f) * TWO_PI);
|
|
c_ang = PXcos(((float)g_targetPan / 4096.0f) * TWO_PI);
|
|
|
|
int sang = FIXED_POINT_ANG(s_ang);
|
|
int cang = FIXED_POINT_ANG(c_ang);
|
|
|
|
point_world.x = (float)(origin_world.x + (COMPASS_LENGTH * sang / 4096));
|
|
point_world.y = origin_world.y;
|
|
point_world.z = (float)(origin_world.z + (COMPASS_LENGTH * cang / 4096));
|
|
|
|
PXWorldToFilm(point_world, camera, result, point_scrn);
|
|
|
|
dx = NEAREST_INT(point_scrn.x - origin_scrn.x);
|
|
dy = NEAREST_INT(point_scrn.y - origin_scrn.y);
|
|
|
|
CHECKDXDY(dx, dy)
|
|
|
|
General_draw_line_24_32(COMPASS_OX, COMPASS_OY, (int16)(COMPASS_OX + dx), (int16)(COMPASS_OY - dy), &turq, ad, pitch);
|
|
|
|
s_ang = PXsin(((float)g_playerPan / 4096.0f) * TWO_PI);
|
|
c_ang = PXcos(((float)g_playerPan / 4096.0f) * TWO_PI);
|
|
|
|
sang = FIXED_POINT_ANG(s_ang);
|
|
cang = FIXED_POINT_ANG(c_ang);
|
|
|
|
point_world.x = (float)(origin_world.x + (COMPASS_LENGTH * sang / 4096));
|
|
point_world.y = origin_world.y;
|
|
point_world.z = (float)(origin_world.z + (COMPASS_LENGTH * cang / 4096));
|
|
PXWorldToFilm(point_world, camera, result, point_scrn);
|
|
|
|
dx = NEAREST_INT(point_scrn.x - origin_scrn.x);
|
|
dy = NEAREST_INT(point_scrn.y - origin_scrn.y);
|
|
|
|
CHECKDXDY(dx, dy)
|
|
|
|
General_draw_line_24_32(COMPASS_OX, COMPASS_OY, (int16)(COMPASS_OX + dx), (int16)(COMPASS_OY - dy), &purple, ad, pitch);
|
|
|
|
surface_manager->Unlock_surface(working_buffer_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End of namespace ICB
|