Files
perfect_dark/src/game/game_0b0fd0.c
T

728 lines
15 KiB
C

#include <ultra64.h>
#include "constants.h"
#include "game/cheats.h"
#include "game/inv.h"
#include "game/bondgun.h"
#include "game/game_0b0fd0.h"
#include "game/player.h"
#include "game/hudmsg.h"
#include "game/playermgr.h"
#include "game/mplayer/setup.h"
#include "game/botcmd.h"
#include "game/lang.h"
#include "game/mplayer/mplayer.h"
#include "game/options.h"
#include "bss.h"
#include "data.h"
#include "types.h"
struct weapon *weaponFindById(s32 itemid)
{
if (itemid < 0) {
return NULL;
}
if (itemid >= ARRAYCOUNT(g_Weapons)) {
return NULL;
}
return g_Weapons[itemid];
}
struct weaponfunc *weaponGetFunctionById(u32 weaponnum, u32 which)
{
struct weapon *weapon = weaponFindById(weaponnum);
if (weapon) {
return weapon->functions[which];
}
return NULL;
}
struct weaponfunc *gsetGetWeaponFunction2(struct gset *gset)
{
struct weapon *weapon = weaponFindById(gset->weaponnum);
if (weapon) {
return weapon->functions[gset->weaponfunc];
}
return NULL;
}
struct weaponfunc *gsetGetWeaponFunction(struct gset *gset)
{
struct weapon *weapon = g_Weapons[gset->weaponnum];
if (weapon) {
#ifdef AVOID_UB
// SuperDragon grenades have FUNC_2, so this can happen
if (gset->weaponfunc > FUNC_SECONDARY) {
return NULL;
}
#endif
return weapon->functions[gset->weaponfunc];
}
return NULL;
}
struct weaponfunc *weaponGetFunction(struct gset *gset, s32 which)
{
struct weapon *weapon = g_Weapons[gset->weaponnum];
if (weapon) {
return weapon->functions[which];
}
return NULL;
}
struct weaponfunc *currentPlayerGetWeaponFunction(u32 hand)
{
struct weapon *weapon = weaponFindById(g_Vars.currentplayer->hands[hand].gset.weaponnum);
if (weapon) {
return weapon->functions[g_Vars.currentplayer->hands[hand].gset.weaponfunc];
}
return NULL;
}
u32 weaponGetNumFunctions(u32 weaponnum)
{
struct weapon *weapon = weaponFindById(weaponnum);
s32 i;
if (!weapon) {
return 0;
}
for (i = 0; i < 2; i++) {
if (weapon->functions[i] == NULL) {
return i;
}
}
return 2;
}
struct invaimsettings *gsetGetAimSettings(struct gset *gset)
{
struct weapon *weapon = weaponFindById(gset->weaponnum);
if (weapon) {
return weapon->aimsettings;
}
return &invaimsettings_default;
}
struct inventory_ammo *weaponGetAmmoByFunction(u32 weaponnum, u32 funcnum)
{
struct weapon *weapon = weaponFindById(weaponnum);
struct weaponfunc *func = weaponGetFunctionById(weaponnum, funcnum);
if (func && weapon && func->ammoindex >= 0) {
return weapon->ammos[func->ammoindex];
}
return NULL;
}
void currentPlayerGetWeaponPos(struct coord *pos)
{
struct weapon *weapon = weaponFindById(bgunGetWeaponNum(HAND_RIGHT));
if (weapon) {
pos->x = weapon->posx;
pos->y = weapon->posy;
pos->z = weapon->posz;
}
}
void currentPlayerSetWeaponPos(struct coord *pos)
{
struct weapon *weapon = weaponFindById(bgunGetWeaponNum(HAND_RIGHT));
if (weapon) {
weapon->posx = pos->x;
weapon->posy = pos->y;
weapon->posz = pos->z;
}
}
f32 handGetXShift(s32 handnum)
{
return g_Vars.currentplayer->hands[handnum].xshift;
}
f32 func0f0b131c(s32 hand)
{
f32 x;
struct weapon *weapon;
if (hand == 0) {
weapon = weaponFindById(bgunGetWeaponNum2(0));
x = weapon->posx;
if (PLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL) {
x -= 3.5f;
if (g_Vars.currentplayernum == 0) {
x += 2.0f;
}
}
} else {
weapon = weaponFindById(bgunGetWeaponNum2(1));
x = -weapon->posx;
if (PLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL) {
x += 3.5f;
if (g_Vars.currentplayernum == 0) {
x += 2.0f;
}
}
}
return x;
}
f32 currentPlayerGetGunZoomFov(void)
{
s32 index = -1;
struct weapon *weapon;
switch (bgunGetWeaponNum2(0)) {
case WEAPON_SNIPERRIFLE:
index = 0;
break;
case WEAPON_FARSIGHT:
index = 1;
break;
case WEAPON_HORIZONSCANNER:
index = 2;
break;
}
if (index >= 0) {
return g_Vars.currentplayer->gunzoomfovs[index];
}
weapon = weaponFindById(bgunGetWeaponNum2(0));
if (weapon) {
f32 fov = weapon->aimsettings->zoomfov;
return ADJUST_ZOOM_FOV(fov);
}
return 0;
}
void currentPlayerZoomOut(f32 fovpersec)
{
s32 index = -1;
switch (bgunGetWeaponNum2(0)) {
case WEAPON_SNIPERRIFLE:
index = 0;
break;
case WEAPON_FARSIGHT:
index = 1;
break;
case WEAPON_HORIZONSCANNER:
index = 2;
break;
}
if (index >= 0) {
f32 amount = fovpersec * 0.25f * LVUPDATE60FREAL();
if (bgunGetWeaponNum2(0) == WEAPON_FARSIGHT) {
amount *= 0.5f;
}
g_Vars.currentplayer->gunzoomfovs[index] *= 1.0f + amount * 0.1f;
if (g_Vars.currentplayer->gunzoomfovs[index] > ADJUST_ZOOM_FOV(60)) {
g_Vars.currentplayer->gunzoomfovs[index] = ADJUST_ZOOM_FOV(60);
}
}
}
void currentPlayerZoomIn(f32 fovpersec)
{
s32 index = -1;
switch (bgunGetWeaponNum2(0)) {
case WEAPON_SNIPERRIFLE:
index = 0;
break;
case WEAPON_FARSIGHT:
index = 1;
break;
case WEAPON_HORIZONSCANNER:
index = 2;
break;
}
if (index >= 0) {
f32 amount = fovpersec * 0.25f * LVUPDATE60FREAL();
if (bgunGetWeaponNum2(0) == WEAPON_FARSIGHT) {
amount *= 0.5f;
}
g_Vars.currentplayer->gunzoomfovs[index] /= 1 + amount * 0.1f;
if (g_Vars.currentplayer->gunzoomfovs[index] < ADJUST_ZOOM_FOV(2)) {
g_Vars.currentplayer->gunzoomfovs[index] = ADJUST_ZOOM_FOV(2);
}
}
}
bool weaponHasFlag(s32 itemid, u32 flag)
{
struct weapon *weapon = weaponFindById(itemid);
if (!weapon) {
return false;
}
return (weapon->flags & flag) != 0;
}
bool weaponHasAimFlag(s32 weaponnum, u32 flag)
{
struct weapon *weapon = weaponFindById(weaponnum);
if (!weapon) {
return false;
}
return (weapon->aimsettings->flags & flag) != 0;
}
bool weaponHasAmmoFlag(s32 weaponnum, s32 funcnum, u32 flag)
{
struct weapon *weapon = weaponFindById(weaponnum);
struct inventory_ammo *ammo;
if (weapon == NULL) {
return false;
}
ammo = weapon->ammos[funcnum];
if (ammo) {
return (ammo->flags & flag) != 0;
}
return false;
}
void func0f0b18ac(s32 arg0)
{
// empty
}
void func0f0b18b4(s32 arg0)
{
// empty
}
s32 currentPlayerGetDeviceState(s32 weaponnum)
{
struct weapon *weapon = weaponFindById(weaponnum);
s32 i;
if (!weapon) {
return DEVICESTATE_UNEQUIPPED;
}
for (i = 0; i < ARRAYCOUNT(weapon->functions); i++) {
if (weapon->functions[i]) {
struct weaponfunc_device *devicefunc = weapon->functions[i];
if ((devicefunc->base.type & 0xff) == INVENTORYFUNCTYPE_DEVICE) {
if ((g_Vars.currentplayer->devicesactive & devicefunc->device) == 0) {
return DEVICESTATE_INACTIVE;
}
return DEVICESTATE_ACTIVE;
}
}
}
return DEVICESTATE_UNEQUIPPED;
}
void currentPlayerSetDeviceActive(s32 weaponnum, bool active)
{
struct weapon *weapon = weaponFindById(weaponnum);
s32 i;
if (!weapon) {
return;
}
for (i = 0; i < ARRAYCOUNT(weapon->functions); i++) {
if (weapon->functions[i]) {
struct weaponfunc_device *devicefunc = weapon->functions[i];
if ((devicefunc->base.type & 0xff) == INVENTORYFUNCTYPE_DEVICE) {
if (active) {
if (devicefunc->device & (DEVICE_NIGHTVISION | DEVICE_XRAYSCANNER | DEVICE_EYESPY | DEVICE_IRSCANNER)) {
g_Vars.currentplayer->devicesactive &= ~(DEVICE_NIGHTVISION | DEVICE_XRAYSCANNER | DEVICE_EYESPY | DEVICE_IRSCANNER);
}
g_Vars.currentplayer->devicesactive |= devicefunc->device;
return;
}
g_Vars.currentplayer->devicesactive &= ~devicefunc->device;
return;
}
}
}
}
u16 weaponGetFileNum(s32 weaponnum)
{
struct weapon *weapon = NULL;
if (weaponnum != -1) {
weapon = g_Weapons[weaponnum];
}
if (weapon) {
#ifdef PLATFORM_N64
if (PLAYERCOUNT() >= 2) {
return weapon->lo_model;
}
#endif
return weapon->hi_model;
}
return 0;
}
u16 weaponGetFileNum2(s32 weaponnum)
{
return weaponGetFileNum(weaponnum);
}
void gsetPopulateFromCurrentPlayer(s32 handnum, struct gset *gset)
{
gset->weaponnum = g_Vars.currentplayer->gunctrl.weaponnum;
gset->weaponfunc = g_Vars.currentplayer->hands[handnum].gset.weaponfunc;
gset->unk063a = g_Vars.currentplayer->hands[handnum].gset.unk063a;
gset->unk0639 = g_Vars.currentplayer->hands[handnum].gset.unk0639;
if (gset->weaponnum == WEAPON_MAULER) {
gset->unk063a = g_Vars.currentplayer->hands[handnum].matmot1 * 10.0f;
}
if (gset->weaponnum == WEAPON_LASER) {
gset->unk063a = g_Vars.currentplayer->hands[handnum].burstbullets & 0xff;
}
}
struct inventory_ammo *gsetGetAmmoDefinition(struct gset *gset)
{
struct weaponfunc *func = gsetGetWeaponFunction(gset);
struct weapon *weapon = weaponFindById(gset->weaponnum);
if (func && func->ammoindex >= 0) {
return weapon->ammos[func->ammoindex];
}
return NULL;
}
u8 gsetGetSinglePenetration(struct gset *gset)
{
struct weaponfunc *func = gsetGetWeaponFunction(gset);
if (func && (func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
struct weaponfunc_shoot *funcshoot = (struct weaponfunc_shoot *)func;
return funcshoot->penetration;
}
return 0;
}
s32 handGetCasingEject(struct gset *gset)
{
s32 result = 0;
struct inventory_ammo *ammo = gsetGetAmmoDefinition(gset);
if (ammo) {
result = ammo->casingeject;
}
return result;
}
f32 gsetGetImpactForce(struct gset *gset)
{
struct weaponfunc *func = gsetGetWeaponFunction(gset);
f32 result = 0;
if (func && (func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
struct weaponfunc_shoot *funcshoot = (struct weaponfunc_shoot *)func;
result = funcshoot->impactforce;
}
return result;
}
f32 gsetGetDamage(struct gset *gset)
{
struct weaponfunc *func = gsetGetWeaponFunction(gset);
f32 damage = 0;
if (func) {
if ((func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
struct weaponfunc_shoot *shootfunc = (struct weaponfunc_shoot *)func;
damage = shootfunc->damage;
}
if ((func->type & 0xff) == INVENTORYFUNCTYPE_MELEE) {
struct weaponfunc_melee *meleefunc = (struct weaponfunc_melee *)func;
damage = meleefunc->damage;
if (gset->weaponnum == WEAPON_REAPER) {
damage *= LVUPDATE60FREAL();
}
}
if ((func->type & 0xff) == INVENTORYFUNCTYPE_THROW) {
struct weaponfunc_throw *throwfunc = (struct weaponfunc_throw *)func;
damage = throwfunc->damage;
}
}
if (gset->weaponnum == WEAPON_MAULER) {
damage = (gset->unk063a / 3.0f + 1.0f) * damage;
}
if (bgunIsFiring(HAND_LEFT) && bgunIsFiring(HAND_RIGHT)) {
damage += damage;
}
return damage;
}
u8 gsetGetFireslotDuration(struct gset *gset)
{
#if VERSION >= VERSION_PAL_FINAL
struct weaponfunc *func = gsetGetWeaponFunction(gset);
u8 result = 0;
if (func && (func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
struct weaponfunc_shoot *funcshoot = (struct weaponfunc_shoot *)func;
result = funcshoot->duration60;
}
if (result >= 4) {
result = TICKS(result);
}
return result;
#else
struct weaponfunc *func = gsetGetWeaponFunction(gset);
if (func && (func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
struct weaponfunc_shoot *funcshoot = (struct weaponfunc_shoot *)func;
return funcshoot->duration60;
}
return 0;
#endif
}
u16 gsetGetSingleShootSound(struct gset *gset)
{
struct weaponfunc *func = gsetGetWeaponFunction(gset);
if (func && (func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
struct weaponfunc_shoot *funcshoot = (struct weaponfunc_shoot *)func;
return funcshoot->shootsound;
}
return 0;
}
bool gsetHasFunctionFlags(struct gset *gset, u32 flags)
{
struct weaponfunc *func = gsetGetWeaponFunction(gset);
if (func) {
return (func->flags & flags) == flags;
}
return false;
}
s8 weaponGetNumTicksPerShot(u32 weaponnum, u32 funcindex)
{
u32 stack[2];
s32 result = 0;
struct weapon *weapon = weaponFindById(weaponnum);
struct weaponfunc *func = weapon->functions[funcindex];
if (func && func->type == INVENTORYFUNCTYPE_SHOOT_AUTOMATIC) {
struct weaponfunc_shootauto *autofunc = (struct weaponfunc_shootauto *)func;
result = 3600.0f / autofunc->maxrpm;
}
#if VERSION != VERSION_PAL_BETA
// PAL beta removes this check, only for it to be added back in PAL final
if (result > 3) {
result = TICKS(result);
}
#endif
return result;
}
u32 currentPlayerGetSight(void)
{
struct weaponfunc *func = weaponGetFunctionById(
g_Vars.currentplayer->hands[HAND_RIGHT].gset.weaponnum,
g_Vars.currentplayer->hands[HAND_RIGHT].gset.weaponfunc);
if (func && (func->type & 0xff) == INVENTORYFUNCTYPE_MELEE) {
return SIGHT_NONE;
}
if (cheatIsActive(CHEAT_CLASSICSIGHT)) {
return SIGHT_CLASSIC;
}
switch (g_Vars.currentplayer->hands[HAND_RIGHT].gset.weaponnum) {
case WEAPON_HORIZONSCANNER:
return SIGHT_NONE;
case WEAPON_NONE:
case WEAPON_UNARMED:
case WEAPON_FALCON2:
case WEAPON_FALCON2_SILENCER:
case WEAPON_DY357MAGNUM:
case WEAPON_DY357LX:
case WEAPON_CMP150:
case WEAPON_CYCLONE:
case WEAPON_RCP120:
case WEAPON_SHOTGUN:
case WEAPON_DEVASTATOR:
case WEAPON_ROCKETLAUNCHER:
case WEAPON_SLAYER:
case WEAPON_COMBATKNIFE:
case WEAPON_CROSSBOW:
case WEAPON_TRANQUILIZER:
case WEAPON_LASER:
case WEAPON_GRENADE:
case WEAPON_NBOMB:
case WEAPON_TIMEDMINE:
case WEAPON_PROXIMITYMINE:
case WEAPON_REMOTEMINE:
case WEAPON_ECMMINE:
return SIGHT_DEFAULT;
case WEAPON_FALCON2_SCOPE:
case WEAPON_MAGSEC4:
case WEAPON_SNIPERRIFLE:
case WEAPON_LAPTOPGUN:
case WEAPON_DRAGON:
case WEAPON_K7AVENGER:
case WEAPON_AR34:
case WEAPON_SUPERDRAGON:
return SIGHT_ZOOM;
case WEAPON_MAULER:
case WEAPON_REAPER:
return SIGHT_SKEDAR;
case WEAPON_PHOENIX:
case WEAPON_CALLISTO:
case WEAPON_FARSIGHT:
return SIGHT_MAIAN;
case WEAPON_PP9I:
case WEAPON_CC13:
case WEAPON_KL01313:
case WEAPON_KF7SPECIAL:
case WEAPON_ZZT:
case WEAPON_DMC:
case WEAPON_AR53:
case WEAPON_RCP45:
return SIGHT_CLASSIC;
}
return SIGHT_DEFAULT;
}
void gsetGetNoiseSettings(struct gset *gset, struct noisesettings *dst)
{
struct noisesettings *settings = NULL;
struct weaponfunc *func = gsetGetWeaponFunction(gset);
if (func != NULL) {
settings = func->noisesettings;
}
if (settings == NULL) {
settings = &invnoisesettings_silent;
}
dst->minradius = settings->minradius;
dst->maxradius = settings->maxradius;
dst->incradius = settings->incradius;
dst->decbasespeed = settings->decbasespeed;
dst->decremspeed = settings->decremspeed;
}
struct guncmd *handGetEquipAnim(struct gset *gset)
{
struct weapon *weapon = g_Weapons[gset->weaponnum];
if (weapon) {
return weapon->equip_animation;
}
return NULL;
}
struct guncmd *handGetUnequipAnim(struct gset *gset)
{
struct weapon *weapon = g_Weapons[gset->weaponnum];
if (weapon) {
return weapon->unequip_animation;
}
return NULL;
}
struct guncmd *gsetGetPriToSecAnim(struct gset *gset)
{
struct weapon *weapon = g_Weapons[gset->weaponnum];
if (weapon) {
return weapon->pritosec_animation;
}
return NULL;
}
struct guncmd *gsetGetSecToPriAnim(struct gset *gset)
{
struct weapon *weapon = g_Weapons[gset->weaponnum];
if (weapon) {
return weapon->sectopri_animation;
}
return NULL;
}