aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/g_supp.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/g_supp.cpp
downloadopenparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz
openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip
initial importHEADmain
Diffstat (limited to 'src/parsec/g_supp.cpp')
-rw-r--r--src/parsec/g_supp.cpp679
1 files changed, 679 insertions, 0 deletions
diff --git a/src/parsec/g_supp.cpp b/src/parsec/g_supp.cpp
new file mode 100644
index 0000000..31069d0
--- /dev/null
+++ b/src/parsec/g_supp.cpp
@@ -0,0 +1,679 @@
+/*
+ * PARSEC - Supporting Functions
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:37 $
+ *
+ * Orginally written by:
+ * Copyright (c) Markus Hadwiger <msh@parsec.org> 1996-1999
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// C library
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+#include "od_class.h"
+
+// global externals
+#include "globals.h"
+
+// subsystem headers
+#include "aud_defs.h"
+#include "inp_defs.h"
+#include "net_defs.h"
+
+// drawing subsystem
+#include "d_font.h"
+
+// mathematics header
+#include "utl_math.h"
+
+// local module header
+#include "g_supp.h"
+
+// proprietary module headers
+#include "con_aux.h"
+#include "con_com.h"
+#include "con_main.h"
+#include "g_camera.h"
+#include "g_stars.h"
+#include "h_drwhud.h"
+#include "obj_ctrl.h"
+#include "obj_game.h"
+#include "obj_part.h"
+#include "part_api.h"
+#include "g_sfx.h"
+#include "g_wfx.h"
+#include "g_emp.h"
+
+
+// flags
+#define PROPULSION_PARTICLES_POSSIBLE
+#define ALLOW_CROSSHAIR_TARGET
+
+
+
+// join position control ------------------------------------------------------
+//
+#define JP_M_S_D 500 // minimum join position distance
+#define JP_RANGE 1000 // maximum join position range
+#define JP_OFS (JP_RANGE/2)
+
+
+// reset position control -----------------------------------------------------
+//
+#define RESET_RANGE 1000
+#define RESET_OFS (RESET_RANGE/2)
+
+
+// init exit function keys for info screen ------------------------------------
+//
+void PrepInfoScreenKeys()
+{
+ DepressedKeys->key_Escape = 0;
+ SELECT_KEYS_RESET();
+}
+
+
+// check if exit function invoked in info screen ------------------------------
+//
+int CheckInfoScreenExit()
+{
+ if ( DepressedKeys->key_Escape || SELECT_KEYS_PRESSED() ) {
+ DepressedKeys->key_Escape = 0;
+ SELECT_KEYS_RESET();
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+// init structure of local ship (central helper function) ---------------------
+//
+PRIVATE
+void InitMyShipStructure( dword myclassid )
+{
+ // free attached clusters
+ PRT_FreeAttachedClusterList( MyShip );
+
+ //NOTE:
+ // if this is called from within a demo it is not entirely sure
+ // that the supplied class id is indeed valid. this may happen
+ // if a recorded ship is not loaded during replay, for instance.
+
+ // fall back to first ship if class is invalid
+ if ( myclassid >= (dword)NumObjClasses ) {
+ myclassid = SHIP_CLASS_1;
+ }
+ ASSERT( ObjClasses[ myclassid ] != NULL );
+ if ( !OBJECT_TYPE_SHIP( ObjClasses[ myclassid ] ) ) {
+ myclassid = SHIP_CLASS_1;
+ }
+
+ // re-init ship object structure
+ ShipObject *shippo = (ShipObject *) ObjClasses[ myclassid ];
+ ASSERT( shippo->InstanceSize <= MyShipMaxInstanceSize );
+ memcpy( MyShip, shippo, shippo->InstanceSize );
+ OBJ_CorrectObjectInstance( MyShip, shippo );
+
+ // attach static particles that are
+ // part of the object instance
+ if ( AUX_ATTACH_OBJECT_PARTICLES ) {
+ OBJ_AttachClassParticles( MyShip );
+ }
+}
+
+
+// init local player's ship ---------------------------------------------------
+//
+void InitLocalShipStatus( dword myclassid )
+{
+ // init local ship object structure
+ InitMyShipStructure( myclassid );
+
+ ShipDowned = FALSE;
+}
+
+
+// advance camera in direction of flight --------------------------------------
+//
+void MoveLocalShip()
+{
+ if ( AUX_FLAGWORD_SCREENSHOT_HELPERS & 0x01 ) {
+ // allow position advance disabling for screenshots
+ return;
+ }
+
+ fixed_t speedadvance = MyShip->CurSpeed * CurScreenRefFrames;
+
+ if ( speedadvance != 0 ) {
+
+ ShipViewCamera[ 2 ][ 3 ] -= FIXED_TO_GEOMV( speedadvance );
+
+ if ( !ObjCameraActive ) {
+
+ PseudoStarMovement[ 2 ][ 3 ] -= FIXED_TO_GEOMV( speedadvance );
+// CameraMoved = 1;
+
+ } else {
+
+ Vector3 dirvec;
+ DirVctMUL( ObjectCamera, FIXED_TO_GEOMV( speedadvance ), &dirvec );
+ PseudoStarMovement[ 0 ][ 3 ] -= dirvec.X;
+ PseudoStarMovement[ 1 ][ 3 ] -= dirvec.Y;
+ PseudoStarMovement[ 2 ][ 3 ] -= dirvec.Z;
+// CameraMoved = 1;
+ }
+
+#ifdef PROPULSION_PARTICLES_POSSIBLE
+
+ if ( AUX_CREATE_PROPULSION_FUMES ) {
+
+ if ( ( MyShip->FumeCount -= CurScreenRefFrames ) < 0 ) {
+
+ int fcadd = ( MyShip->MaxSpeed - MyShip->CurSpeed ) / 256;
+ MyShip->FumeCount = MyShip->FumeFreq + fcadd;
+
+ SFX_CreatePropulsionParticles( MyShip );
+ }
+ }
+#endif
+
+ }
+}
+
+
+// init object camera ---------------------------------------------------------
+//
+void ObjCamOn()
+{
+ if ( !ObjCameraActive ) {
+
+ ObjCameraActive = 1;
+
+ extern int objcam_textcount; // defined in H_DRWHUD.C
+ objcam_textcount = 0;
+
+ // insert local player's ship into ship objects list
+ ASSERT( PShipObjects->NextObj != MyShip );
+ ASSERT( MyShip->NextObj == NULL );
+ MyShip->NextObj = PShipObjects->NextObj;
+ PShipObjects->NextObj = MyShip;
+
+ // init start matrix of object camera (euler angles and distance)
+ MakeIdMatrx( ObjectCamera );
+ CamRotX( ObjectCamera, MyShip->ObjCamStartPitch );
+ CamRotY( ObjectCamera, MyShip->ObjCamStartYaw );
+ CamRotZ( ObjectCamera, MyShip->ObjCamStartRoll );
+ ObjectCamera[ 2 ][ 3 ] += MyShip->ObjCamStartDist;
+
+ // do new random placement of pseudo stars
+ NumPseudoStars = 0;
+ InitPseudoStars();
+ }
+}
+
+
+// kill object camera ---------------------------------------------------------
+//
+void ObjCamOff()
+{
+ if ( ObjCameraActive ) {
+
+ ObjCameraActive = 0;
+
+ // unlink local player's ship from ship objects list
+ ASSERT( PShipObjects->NextObj == MyShip );
+ PShipObjects->NextObj = MyShip->NextObj;
+ MyShip->NextObj = NULL;
+
+ // do new random placement of pseudo stars
+ NumPseudoStars = 0;
+ InitPseudoStars();
+ }
+}
+
+
+// handle object camera enabling/disabling via keypress -----------------------
+//
+void ObjectCameraControl()
+{
+ // toggle object camera
+ if ( DepressedKeys->key_ToggleObjCamera ) {
+ DepressedKeys->key_ToggleObjCamera = 0;
+
+ // toggling only allowed outside entrymode/floating menu
+ if ( GAME_MODE_ACTIVE() ) {
+
+ if ( ObjCameraActive ) {
+ ObjCamOff();
+ } else {
+ ObjCamOn();
+ }
+ }
+ }
+}
+
+
+// init local ship in floating menu -------------------------------------------
+//
+void InitFloatingMyShip()
+{
+ // (re-)init local ship object structure
+ InitMyShipStructure( MyShip->ObjectClass );
+
+ // init pseudo- and fixed stars
+ NumPseudoStars = 0;
+ InitPseudoStars();
+
+ // select standard laser and dumb missile
+ SelectedLaser = 0;
+ SelectedMissile = 0;
+
+ // remove target lock
+ TargetObjNumber = TARGETID_NO_TARGET;
+ TargetVisible = FALSE;
+}
+
+
+// init ship position for joining network game --------------------------------
+//
+void InitJoinPosition()
+{
+ // get pointer to another ship (any other ship will do)
+ GenObject *shippo = FetchFirstShip();
+
+ // change position only when in PEER mode. in GMSV join position comes from server
+ if ( NET_ConnectedPEER() ) {
+
+ MakeIdMatrx( ShipViewCamera );
+ if ( shippo != NULL ) {
+
+ int xdist = ( RAND() % JP_RANGE ) - JP_OFS;
+ int ydist = ( RAND() % JP_RANGE ) - JP_OFS;
+ int zdist = ( RAND() % JP_RANGE ) - JP_OFS;
+
+ xdist += ( xdist < 0 ) ? -JP_M_S_D : JP_M_S_D;
+ ydist += ( ydist < 0 ) ? -JP_M_S_D : JP_M_S_D;
+ zdist += ( zdist < 0 ) ? -JP_M_S_D : JP_M_S_D;
+
+ ShipViewCamera[ 0 ][ 3 ] = -shippo->ObjPosition[ 0 ][ 3 ] + INT_TO_GEOMV( xdist );
+ ShipViewCamera[ 1 ][ 3 ] = -shippo->ObjPosition[ 1 ][ 3 ] + INT_TO_GEOMV( ydist );
+ ShipViewCamera[ 2 ][ 3 ] = -shippo->ObjPosition[ 2 ][ 3 ] + INT_TO_GEOMV( zdist );
+ }
+ }
+
+ // reset view camera smoothing filter
+ CAMERA_ResetFilter();
+
+ // (re-)init local ship object structure
+ InitMyShipStructure( MyShip->ObjectClass );
+
+ //NOTE:
+ // the call of CalcOrthoInverse() is not really necessary
+ // here, since the matrix is translation-only anyway.
+ // maybe this will change in the future, but not likely.
+
+ // store ship position in world-space
+ CalcOrthoInverse( ShipViewCamera, MyShip->ObjPosition );
+
+ // init pseudo- and fixed stars
+ NumPseudoStars = 0;
+ InitPseudoStars();
+
+ // select standard laser and dumb missile
+ SelectedLaser = 0;
+ SelectedMissile = 0;
+
+ // remove target lock
+ TargetObjNumber = TARGETID_NO_TARGET;
+ TargetVisible = FALSE;
+}
+
+
+// prepare join replayed from recorded network game ---------------------------
+//
+void InitJoinReplay()
+{
+ // (re-)init local ship object structure
+ InitMyShipStructure( MyShip->ObjectClass );
+
+ MakeIdMatrx( ShipViewCamera );
+ MakeIdMatrx( MyShip->ObjPosition );
+
+ // init pseudo- and fixed stars
+ NumPseudoStars = 0;
+ InitPseudoStars();
+
+ // select standard laser and dumb missile
+ SelectedLaser = 0;
+ SelectedMissile = 0;
+
+ // remove target lock
+ TargetObjNumber = TARGETID_NO_TARGET;
+ TargetVisible = FALSE;
+}
+
+
+// set origin of ship to defined location (called by console command) ---------
+//
+void Cmd_SetShipOrigin()
+{
+ // init position in proximity of origin (0,0,0)
+ MakeIdMatrx( ShipViewCamera );
+ geomv_t xdist = INT_TO_GEOMV( ( RAND() % RESET_RANGE ) - RESET_OFS );
+ geomv_t ydist = INT_TO_GEOMV( ( RAND() % RESET_RANGE ) - RESET_OFS );
+ geomv_t zdist = INT_TO_GEOMV( ( RAND() % RESET_RANGE ) - RESET_OFS );
+
+ ShipViewCamera[ 0 ][ 3 ] = xdist;
+ ShipViewCamera[ 1 ][ 3 ] = ydist;
+ ShipViewCamera[ 2 ][ 3 ] = zdist;
+
+ // reset view camera smoothing filter
+ CAMERA_ResetFilter();
+
+ // (re-)init local ship object structure
+ InitMyShipStructure( MyShip->ObjectClass );
+
+ //NOTE:
+ // the call of CalcOrthoInverse() is not really necessary
+ // here, since the matrix is translation-only anyway.
+ // maybe this will change in the future, but not likely.
+
+ // store ship position in world-space
+ CalcOrthoInverse( ShipViewCamera, MyShip->ObjPosition );
+
+ // init pseudo- and fixed stars
+ NumPseudoStars = 0;
+ InitPseudoStars();
+
+ // select standard laser and dumb missile
+ SelectedLaser = 0;
+ SelectedMissile = 0;
+
+ // remove target lock
+ TargetObjNumber = TARGETID_NO_TARGET;
+ TargetVisible = FALSE;
+}
+
+
+// select target at crosshair -------------------------------------------------
+//
+void SelectCrosshairTarget()
+{
+
+#ifdef ALLOW_CROSSHAIR_TARGET
+
+ if ( ObjCameraActive )
+ return;
+
+ // walk ship list and select first ship encountered
+ // as target if in tracking bounding-box
+ ShipObject *shippo = FetchFirstShip();
+
+ for ( ; shippo; shippo = (ShipObject *) shippo->NextObj ) {
+
+ // check if ship allowed as target
+ if ( ( shippo->ExplosionCount == 0 ) ||
+ ( shippo->ExplosionCount >= BM_EXPLNOTARGFRAME * EXPL_REF_SPEED ) ) {
+
+ Vertex3 Pos, ViewPos;
+
+ // position of ship in viewspace
+ FetchTVector( shippo->ObjPosition, &Pos );
+ MtxVctMUL( ShipViewCamera, &Pos, &ViewPos );
+
+ // cull objects behind local ship
+ if ( ViewPos.Z <= GEOMV_0 )
+ continue;
+
+ // calc position of ship in screenspace
+ SPoint sloc;
+ PROJECT_TO_SCREEN( ViewPos, sloc );
+
+ extern int TrackingLeftBoundX;
+ extern int TrackingRightBoundX;
+ extern int TrackingLeftBoundY;
+ extern int TrackingRightBoundY;
+
+ // check if ship in tracking bounding-box
+ if ( ( sloc.X > TrackingLeftBoundX ) &&
+ ( sloc.X < TrackingRightBoundX ) &&
+ ( sloc.Y > TrackingLeftBoundY ) &&
+ ( sloc.Y < TrackingRightBoundY ) ) {
+
+ // select ship as current target
+ TargetObjNumber = shippo->HostObjNumber;
+ TargetVisible = TRUE;
+
+ if ( ( shippo->HostObjNumber & 0xffff ) == 0 )
+ TargetRemId = GetObjectOwner( shippo );
+ else
+ TargetRemId = TARGETID_NO_TARGET;
+
+ TargetScreenX = sloc.X;
+ TargetScreenY = sloc.Y;
+
+ return;
+ }
+ }
+ }
+
+#endif
+
+}
+
+
+// fetch next target ----------------------------------------------------------
+//
+void SelectNextTarget()
+{
+ dword nexttarget = TARGETID_NO_TARGET;
+ GenObject *objscan = FetchFirstShip();
+
+ // take listhead as default-target
+ if ( objscan != NULL ) {
+ nexttarget = objscan->HostObjNumber;
+ }
+
+ // search for current target
+ while ( objscan && ( objscan->HostObjNumber != TargetObjNumber ) )
+ objscan = objscan->NextObj;
+
+ // if there is an object behind the current target in list take it
+ if ( objscan && objscan->NextObj ) {
+ nexttarget = objscan->NextObj->HostObjNumber;
+ }
+
+ TargetObjNumber = nexttarget;
+}
+
+
+// do ship intelligence -------------------------------------------------------
+//
+void ShipIntelligence()
+{
+ static fixed_t old_speed = 0;
+
+ // ensure old speed gets reset on join
+ if ( MyShip->CurSpeed == 0 ) {
+ old_speed = 0;
+ }
+
+ // (re)start thrust sample on speed change
+ if ( old_speed != MyShip->CurSpeed ) {
+ old_speed = MyShip->CurSpeed;
+ AUD_StartThrust( THRUST_TYPE_NORMAL );
+ }
+
+ // (re)start slidethrust sample on slide change
+ if ( ( CurSlideHorz != GEOMV_0 ) || ( CurSlideVert != GEOMV_0 ) ) {
+ AUD_StartThrust( THRUST_TYPE_SLIDE );
+ }
+
+ // perform afterburner energy depletion
+ if ( MyShip->afterburner_active ) {
+
+ MyShip->afterburner_energy -= CurScreenRefFrames;
+ if ( MyShip->afterburner_energy <= 0 ) {
+ OBJ_DisableAfterBurner( MyShip );
+ }
+ }
+
+ // check autotargeting
+ if ( MyShip->Specials & SPMASK_AUTOTARGETING ) {
+
+ // automatically select next target if old target lost
+ GenObject *targetpo = FetchHostObject( TargetObjNumber );
+ if ( targetpo == NULL ) {
+
+// MSGOUT( "target lost" );
+ SelectNextTarget();
+ }
+ }
+}
+
+
+// call duration weapons maintenance functions --------------------------------
+//
+void MaintainDurationWeapons( int playerid )
+{
+ ASSERT( ( playerid == LocalPlayerId ) || NetConnected );
+ ASSERT( ( playerid != LocalPlayerId ) ||
+ ( NetConnected != NETWORK_GAME_ON ) ||
+ ( NET_FetchOwnersShip( playerid ) == MyShip ) );
+
+ ShipObject *shippo = ( playerid == LocalPlayerId ) ? MyShip : NET_FetchOwnersShip( playerid );
+ ASSERT( shippo != NULL );
+
+ // maintain helix
+ if ( shippo->WeaponsActive & WPMASK_CANNON_HELIX ) {
+ WFX_MaintainHelix( shippo, playerid );
+ }
+
+ // maintain lightning
+ if ( shippo->WeaponsActive & WPMASK_CANNON_LIGHTNING ) {
+ WFX_MaintainLightning( shippo );
+ }
+
+ // maintain photon
+ photon_sphere_pcluster_s* cluster = (photon_sphere_pcluster_s *)
+ PRT_ObjectHasAttachedClustersOfType( shippo, SAT_PHOTON );
+ if ( cluster != NULL ) {
+ WFX_CalcPhotonSphereAnimation( cluster );
+ }
+
+ // maintain emp
+ if ( shippo->WeaponsActive & WPMASK_DEVICE_EMP ) {
+ WFX_CreateEmpWaves( shippo );
+ }
+}
+
+
+// kill duration weapons (make sure they are properly turned off) -------------
+//
+void KillDurationWeapons( ShipObject *shippo )
+{
+ ASSERT( shippo != NULL );
+
+ // kill helix
+ if ( shippo->WeaponsActive & WPMASK_CANNON_HELIX ) {
+
+ // stop sound
+ AUD_HelixOff( shippo );
+ }
+
+ // kill lightning
+ if ( shippo->WeaponsActive & WPMASK_CANNON_LIGHTNING ) {
+
+ // stop sound
+ AUD_LightningOff( shippo );
+ }
+
+ // kill photon
+ if ( shippo->WeaponsActive & WPMASK_CANNON_PHOTON ) {
+
+ // stop sound
+ AUD_PhotonLoadingOff( shippo );
+ }
+
+ // kill emp
+// if ( shippo->WeaponsActive & WPMASK_DEVICE_EMP ) {
+ // nothing to do
+// }
+}
+
+
+// select crosshair target ----------------------------------------------------
+//
+PRIVATE
+int Cmd_CROSSTARGET( char *paramstr )
+{
+ //NOTE:
+ //CONCOM:
+ // crosstarget_command ::= 'crosstarget'
+
+ ASSERT( paramstr != NULL );
+ HANDLE_COMMAND_DOMAIN_SEP( paramstr );
+
+ if ( strtok( paramstr, " " ) == NULL ) {
+
+ if ( GAME_MODE_ACTIVE() ) {
+ SelectCrosshairTarget();
+ }
+
+ } else {
+ CON_AddLine( too_many_args );
+ }
+
+ return TRUE;
+}
+
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( G_SUPP )
+{
+
+#ifdef ALLOW_CROSSHAIR_TARGET
+
+ user_command_s regcom;
+ memset( &regcom, 0, sizeof( user_command_s ) );
+
+ // register "crosstarget" command
+ regcom.command = "crosstarget";
+ regcom.numparams = 0;
+ regcom.execute = Cmd_CROSSTARGET;
+ regcom.statedump = NULL;
+ CON_RegisterUserCommand( &regcom );
+
+#endif // ALLOW_CROSSHAIR_TARGET
+
+}
+
+
+