#include #include "constants.h" #include "game/bondgrab.h" #include "game/bondmove.h" #include "game/cheats.h" #include "game/chraction.h" #include "game/debug.h" #include "game/prop.h" #include "game/objectives.h" #include "game/bondgun.h" #include "game/player.h" #include "game/bondhead.h" #include "game/propobj.h" #include "bss.h" #include "lib/mtx.h" #include "lib/anim.h" #include "lib/collision.h" #include "data.h" #include "types.h" struct prop *var8009de70; u32 var8009de74; struct coord var8009de78; u32 var8009de84; u32 var8009de88; u32 var8009de8c; bool var80070e80 = false; void bgrabInit(void) { s32 prevmode = g_Vars.currentplayer->bondmovemode; Mtxf matrix; struct prop *prop = g_Vars.currentplayer->grabbedprop; g_Vars.currentplayer->bondmovemode = MOVEMODE_GRAB; g_Vars.currentplayer->bondgrabthetaspeedsum = 0; g_Vars.currentplayer->grabbedprevpos.x = prop->pos.x; g_Vars.currentplayer->grabbedprevpos.y = prop->pos.y; g_Vars.currentplayer->grabbedprevpos.z = prop->pos.z; g_Vars.currentplayer->grabbedrotoffset = 0; g_Vars.currentplayer->grabbedforcez = 0; g_Vars.currentplayer->grabbedposoffset.x = prop->pos.x - g_Vars.currentplayer->prop->pos.x; g_Vars.currentplayer->grabbedposoffset.y = prop->pos.y - g_Vars.currentplayer->prop->pos.y; g_Vars.currentplayer->grabbedposoffset.z = prop->pos.z - g_Vars.currentplayer->prop->pos.z; g_Vars.currentplayer->grabbeddoextra = false; g_Vars.currentplayer->grabbedrotextra = 0; g_Vars.currentplayer->grabbedposextra.x = 0; g_Vars.currentplayer->grabbedposextra.y = 0; g_Vars.currentplayer->grabbedposextra.z = 0; g_Vars.currentplayer->grabbedrotextrasum = 0; g_Vars.currentplayer->grabbedposextrasum.x = 0; g_Vars.currentplayer->grabbedposextrasum.y = 0; g_Vars.currentplayer->grabbedposextrasum.z = 0; g_Vars.currentplayer->guncloseroffset = 0; g_Vars.currentplayer->gunextraaimx = 0; g_Vars.currentplayer->gunextraaimy = 0; mtx4LoadYRotation((g_Vars.currentplayer->vv_theta * M_BADTAU) / 360.0f, &matrix); mtx4RotateVecInPlace(&matrix, &g_Vars.currentplayer->grabbedposoffset); g_Vars.currentplayer->bondprevtheta = g_Vars.currentplayer->vv_theta; if (prop->type == PROPTYPE_OBJ || prop->type == PROPTYPE_DOOR || prop->type == PROPTYPE_WEAPON) { struct defaultobj *obj = prop->obj; struct hov *hov = NULL; bool withforce; if (obj->hidden & OBJHFLAG_PROJECTILE) { struct projectile *projectile = obj->projectile; g_Vars.currentplayer->bondshotspeed.x += projectile->speed.x * 0.2f; g_Vars.currentplayer->bondshotspeed.z += projectile->speed.z * 0.2f; objFreeProjectile(obj); } if (obj->type == OBJTYPE_HOVERPROP) { struct hoverpropobj *hoverprop = (struct hoverpropobj *)prop->obj; hov = &hoverprop->hov; } else if (obj->type == OBJTYPE_HOVERBIKE) { struct hoverbikeobj *hoverprop = (struct hoverbikeobj *)prop->obj; hov = &hoverprop->hov; } if (hov) { g_Vars.currentplayer->grabbedrotoffset = hov->unk10 - (M_BADTAU - (g_Vars.currentplayer->vv_theta * M_BADTAU) / 360.0f); if (g_Vars.currentplayer->grabbedrotoffset >= M_BADTAU) { g_Vars.currentplayer->grabbedrotoffset -= M_BADTAU; } else if (g_Vars.currentplayer->grabbedrotoffset < 0) { g_Vars.currentplayer->grabbedrotoffset += M_BADTAU; } } obj->hidden |= OBJHFLAG_GRABBED; if (obj->flags3 & OBJFLAG3_GEOCYL) { withforce = cd000276c8(obj->geocyl, g_Vars.currentplayer->prop->pos.x, g_Vars.currentplayer->prop->pos.z, VERSION >= VERSION_NTSC_1_0 ? 45 : 40, 0, 0); } else { withforce = cd000274e0(obj->geoblock, g_Vars.currentplayer->prop->pos.x, g_Vars.currentplayer->prop->pos.z, VERSION >= VERSION_NTSC_1_0 ? 45 : 40, 0, 0); } if (withforce) { g_Vars.currentplayer->grabbedforcez = VERSION >= VERSION_NTSC_1_0 ? 15 : 10; } } if (prevmode != MOVEMODE_GRAB && prevmode != MOVEMODE_WALK) { s32 i; for (i = 0; i != 3; i++) { g_Vars.currentplayer->bondshotspeed.f[i] = 0; } g_Vars.currentplayer->speedsideways = 0; g_Vars.currentplayer->speedstrafe = 0; g_Vars.currentplayer->speedgo = 0; g_Vars.currentplayer->speedboost = 1; g_Vars.currentplayer->speedmaxtime60 = 0; g_Vars.currentplayer->speedforwards = 0; g_Vars.currentplayer->speedtheta = 0; g_Vars.currentplayer->speedthetacontrol = 0; g_Vars.currentplayer->moveinitspeed.x = 0; g_Vars.currentplayer->moveinitspeed.y = 0; g_Vars.currentplayer->moveinitspeed.z = 0; } g_Vars.currentplayer->grabstarttime = g_Vars.lvframe60; } void bgrabExit(void) { struct coord moveamount; struct defaultobj *obj; f32 rotateamount; if (g_Vars.currentplayer->grabbedprop) { struct defaultobj *obj = g_Vars.currentplayer->grabbedprop->obj; obj->hidden &= ~OBJHFLAG_GRABBED; if (g_Vars.lvupdate240 > 0) { moveamount.x = (g_Vars.currentplayer->grabbedprop->pos.x - g_Vars.currentplayer->grabbedprevpos.x) / g_Vars.lvupdate240freal; moveamount.y = 0; moveamount.z = (g_Vars.currentplayer->grabbedprop->pos.z - g_Vars.currentplayer->grabbedprevpos.z) / g_Vars.lvupdate240freal; rotateamount = -(g_Vars.currentplayer->vv_theta - g_Vars.currentplayer->bondprevtheta) * M_BADTAU / 360; if (rotateamount < -M_PI) { rotateamount += M_BADTAU; } else if (rotateamount >= M_PI) { rotateamount -= M_BADTAU; } rotateamount /= g_Vars.lvupdate240freal; objApplyMomentum(g_Vars.currentplayer->grabbedprop->obj, &moveamount, rotateamount, 0, 0); } g_Vars.currentplayer->grabbedprop = NULL; } } void bgrab0f0ccbf0(struct coord *delta, f32 angle, struct defaultobj *obj) { struct coord spd4; struct coord spc8; struct coord spbc; struct coord spb0; struct coord spa4; struct coord sp98; if (g_Vars.lvupdate240 > 0) { if (var8009de70->type == PROPTYPE_PLAYER) { sp98.x = delta->x + g_Vars.currentplayer->prop->pos.x; sp98.y = g_Vars.currentplayer->prop->pos.y; sp98.z = delta->z + g_Vars.currentplayer->prop->pos.z; #if VERSION >= VERSION_NTSC_1_0 cd00024e4c(&spb0, &spa4, 201, "bondgrab.c"); #else cd00024e4c(&spb0, &spa4, 200, "bondgrab.c"); #endif spc8.x = spa4.z - spb0.z; spc8.y = 0.0f; spc8.z = spb0.x - spa4.x; if (spc8.f[0] != 0.0f || spc8.f[2] != 0.0f) { guNormalize(&spc8.x, &spc8.y, &spc8.z); } else { spc8.z = 1.0f; } func0f02e3dc(&spb0, &spa4, &sp98, &spc8, &spd4); spbc.x = (sp98.x - g_Vars.currentplayer->prop->pos.x) / g_Vars.lvupdate240freal; spbc.y = 0.0f; spbc.z = (sp98.z - g_Vars.currentplayer->prop->pos.z) / g_Vars.lvupdate240freal; func0f082e84(obj, &spd4, &spc8, &spbc, false); } else { struct coord sp8c; struct coord sp80; struct coord sp74 = {0, 0, 0}; struct coord sp68; struct coord sp5c; struct coord sp50; struct coord sp44; #if VERSION >= VERSION_NTSC_1_0 cd00024e4c(&sp68, &sp5c, 228, "bondgrab.c"); #else cd00024e4c(&sp68, &sp5c, 227, "bondgrab.c"); #endif if (cd00025364(&sp50, &sp44)) { sp44.x -= sp50.x; sp44.y -= sp50.y; sp44.z -= sp50.z; } else { sp50.x = var8009de70->pos.x; sp50.y = var8009de70->pos.y; sp50.z = var8009de70->pos.z; sp44.x = obj->prop->pos.x - var8009de70->pos.x; sp44.y = obj->prop->pos.y - var8009de70->pos.y; sp44.z = obj->prop->pos.z - var8009de70->pos.z; } func0f02e3dc(&sp68, &sp5c, &sp50, &sp44, &sp8c); sp80.x = delta->x; sp80.y = 0.0f; sp80.z = delta->z; if (sp80.f[0] != 0.0f || sp80.f[2] != 0.0f) { guNormalize(&sp80.x, &sp80.y, &sp80.z); } else { sp80.z = 1.0f; } if (delta->x != 0.0f) { sp74.x += delta->x / g_Vars.lvupdate240freal; } if (delta->z != 0.0f) { sp74.z += delta->z / g_Vars.lvupdate240freal; } func0f082e84(obj, &sp8c, &sp80, &sp74, false); if (angle != 0.0f) { f32 sp40 = sp8c.x - g_Vars.currentplayer->prop->pos.x; f32 sp3c = sp8c.z - g_Vars.currentplayer->prop->pos.z; f32 rotation = 0.0f; struct coord sp2c = {0, 0, 0}; f32 mult = 1.0f / sqrtf(sp40 * sp40 + sp3c * sp3c); sp40 *= mult; sp3c *= mult; angle = angle / g_Vars.lvupdate240freal; sp2c.x += -sp3c * angle * 40.0f; sp2c.z += sp40 * angle * 40.0f; rotation += angle * 0.1f; objApplyMomentum(obj, &sp2c, rotation, true, true); } } } } bool bgrabTryMoveUpwards(f32 y) { bool result; struct coord newpos; s16 rooms[8]; f32 ymax; f32 ymin; f32 radius; newpos.x = g_Vars.currentplayer->prop->pos.x; newpos.y = g_Vars.currentplayer->prop->pos.y + y; newpos.z = g_Vars.currentplayer->prop->pos.z; playerGetBbox(g_Vars.currentplayer->prop, &radius, &ymax, &ymin); func0f065e74(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->prop->rooms, &newpos, rooms); bmoveFindEnteredRoomsByPos(g_Vars.currentplayer, &newpos, rooms); propSetPerimEnabled(g_Vars.currentplayer->prop, false); ymin -= 0.1f; result = cdTestVolume(&newpos, radius, rooms, CDTYPE_ALL, 1, ymax - g_Vars.currentplayer->prop->pos.y, ymin - g_Vars.currentplayer->prop->pos.y); propSetPerimEnabled(g_Vars.currentplayer->prop, true); if (result == CDRESULT_NOCOLLISION) { g_Vars.currentplayer->prop->pos.y = newpos.y; propDeregisterRooms(g_Vars.currentplayer->prop); roomsCopy(rooms, g_Vars.currentplayer->prop->rooms); } return result; } s32 bgrabCalculateNewPosition(struct coord *delta, f32 angle, bool arg2) { s32 cdresult = CDRESULT_NOCOLLISION; s32 i; struct coord pos; s16 rooms[8]; bool ismoving = false; f32 ymax; f32 ymin; f32 radius; f32 rotextrasum; struct coord posextrasum; f32 rotextra; struct coord posextra; struct defaultobj *obj; struct hov *hov; struct coord sp88; var80070e80 = 0; playerGetBbox(g_Vars.currentplayer->prop, &radius, &ymax, &ymin); propSetPerimEnabled(g_Vars.currentplayer->prop, false); propSetPerimEnabled(g_Vars.currentplayer->grabbedprop, false); pos.x = g_Vars.currentplayer->prop->pos.x; pos.y = g_Vars.currentplayer->prop->pos.y; pos.z = g_Vars.currentplayer->prop->pos.z; if (delta->f[0] != 0.0f || delta->f[1] != 0.0f || delta->f[2] != 0.0f) { pos.x += delta->x; pos.y += delta->y; pos.z += delta->z; func0f065e74(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->prop->rooms, &pos, rooms); #if VERSION < VERSION_NTSC_1_0 { s32 i; for (i = 0; rooms[i] != -1; i++) { if (rooms[i] == g_Vars.currentplayer->floorroom) { rooms[0] = g_Vars.currentplayer->floorroom; rooms[1] = -1; break; } } } #endif bmoveFindEnteredRoomsByPos(g_Vars.currentplayer, &pos, rooms); ismoving = true; cdresult = cd0002d8b8(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->prop->rooms, &pos, rooms, CDTYPE_ALL, true, ymax - g_Vars.currentplayer->prop->pos.y, ymin - g_Vars.currentplayer->prop->pos.y); if (cdresult == CDRESULT_NOCOLLISION) { cdresult = cd0002a6fc(&g_Vars.currentplayer->prop->pos, &pos, radius, rooms, CDTYPE_ALL, true, ymax - g_Vars.currentplayer->prop->pos.y, ymin - g_Vars.currentplayer->prop->pos.y); } if (cdresult != CDRESULT_NOCOLLISION) { var8009de70 = g_Vars.currentplayer->prop; } } propSetPerimEnabled(g_Vars.currentplayer->grabbedprop, true); if (cdresult == CDRESULT_NOCOLLISION) { struct coord sp7c; f32 sp78 = -angle; f32 sp74; f32 sp70; f32 sp6c; obj = g_Vars.currentplayer->grabbedprop->obj; hov = NULL; if (g_Vars.currentplayer->grabbeddoextra) { f32 f0 = -g_Vars.currentplayer->speedtheta * 0.017450513f * 3.5f; if (f0 * 6.0f * 10.0f); sp88.f[0] = f0 * 5.0f * 100.0f + g_Vars.currentplayer->speedsideways * 10.0f; sp88.f[1] = 0.0f; sp88.f[2] = -g_Vars.currentplayer->speedforwards * 10.0f + g_Vars.currentplayer->grabbedforcez; rotextrasum = g_Vars.currentplayer->grabbedrotextrasum; posextrasum.f[0] = g_Vars.currentplayer->grabbedposextrasum.f[0]; posextrasum.f[1] = g_Vars.currentplayer->grabbedposextrasum.f[1]; posextrasum.f[2] = g_Vars.currentplayer->grabbedposextrasum.f[2]; for (i = 0; i < g_Vars.lvupdate240; i++) { rotextrasum = (PAL ? 0.9847f : 0.9873f) * rotextrasum + f0 * 6.0f; posextrasum.f[0] = (PAL ? 0.9847f : 0.9873f) * posextrasum.f[0] + sp88.f[0]; posextrasum.f[1] = (PAL ? 0.9847f : 0.9873f) * posextrasum.f[1] + sp88.f[1]; posextrasum.f[2] = (PAL ? 0.9847f : 0.9873f) * posextrasum.f[2] + sp88.f[2]; } rotextra = rotextrasum * (PAL ? 0.01529997587204f : 0.012700021266937f); posextra.f[0] = posextrasum.f[0] * (PAL ? 0.01529997587204f : 0.012700021266937f); posextra.f[1] = posextrasum.f[1] * (PAL ? 0.01529997587204f : 0.012700021266937f); posextra.f[2] = posextrasum.f[2] * (PAL ? 0.01529997587204f : 0.012700021266937f); } else { rotextra = g_Vars.currentplayer->grabbedrotextra; posextra.f[0] = g_Vars.currentplayer->grabbedposextra.f[0]; posextra.f[1] = g_Vars.currentplayer->grabbedposextra.f[1]; posextra.f[2] = g_Vars.currentplayer->grabbedposextra.f[2]; } sp7c.x = delta->x; sp7c.y = delta->y; sp7c.z = delta->z; if (obj->type == OBJTYPE_HOVERPROP) { struct hoverpropobj *tmp = (struct hoverpropobj *)g_Vars.currentplayer->grabbedprop->obj; hov = &tmp->hov; } else if (obj->type == OBJTYPE_HOVERBIKE) { struct hoverbikeobj *tmp = (struct hoverbikeobj *)g_Vars.currentplayer->grabbedprop->obj; hov = &tmp->hov; } if (hov != NULL) { sp78 = M_BADTAU - g_Vars.currentplayer->vv_theta * M_BADTAU / 360.0f + -angle + g_Vars.currentplayer->grabbedrotoffset - hov->unk10 + rotextra; while (sp78 >= M_PI) { sp78 -= M_BADTAU; } while (sp78 < -M_PI) { sp78 += M_BADTAU; } } if (angle != 0.0f || g_Vars.currentplayer->grabbeddoextra) { f32 f12; f32 f18; sp74 = M_BADTAU - g_Vars.currentplayer->vv_theta * M_BADTAU / 360.0f - angle; if (sp74 >= M_BADTAU) { sp74 -= M_BADTAU; } else if (sp74 < 0.0f) { sp74 += M_BADTAU; } sp70 = cosf(sp74); sp6c = sinf(sp74); f12 = g_Vars.currentplayer->grabbedposoffset.f[0] + posextra.f[0]; f18 = g_Vars.currentplayer->grabbedposoffset.f[2] + posextra.f[2]; sp7c.x = pos.f[0] + f12 * sp70 + f18 * sp6c - g_Vars.currentplayer->grabbedprop->pos.f[0]; sp7c.z = pos.f[2] + f18 * sp70 - f12 * sp6c - g_Vars.currentplayer->grabbedprop->pos.f[2]; } var80070e80 = true; var8009de78.x = g_Vars.currentplayer->grabbedprop->pos.x + sp7c.x; var8009de78.y = g_Vars.currentplayer->grabbedprop->pos.y + sp7c.y; var8009de78.z = g_Vars.currentplayer->grabbedprop->pos.z + sp7c.z; cdresult = func0f072144(g_Vars.currentplayer->grabbedprop->obj, &sp7c, sp78, arg2); if (cdresult != CDRESULT_NOCOLLISION) { var8009de70 = g_Vars.currentplayer->grabbedprop; } } propSetPerimEnabled(g_Vars.currentplayer->prop, true); if (cdresult == CDRESULT_NOCOLLISION) { var8009de70 = NULL; if (arg2) { f32 theta = g_Vars.currentplayer->vv_theta + angle * 360.0f / M_BADTAU; while (theta < 0.0f) { theta += 360.0f; } while (theta >= 360.0f) { theta -= 360.0f; } g_Vars.currentplayer->vv_theta = theta; g_Vars.currentplayer->prop->pos.x = pos.x; g_Vars.currentplayer->prop->pos.y = pos.y; g_Vars.currentplayer->prop->pos.z = pos.z; if (ismoving) { propDeregisterRooms(g_Vars.currentplayer->prop); roomsCopy(rooms, g_Vars.currentplayer->prop->rooms); } if (g_Vars.currentplayer->grabbeddoextra) { g_Vars.currentplayer->grabbedrotextra = rotextra; g_Vars.currentplayer->grabbedposextra.x = posextra.x; g_Vars.currentplayer->grabbedposextra.y = posextra.y; g_Vars.currentplayer->grabbedposextra.z = posextra.z; g_Vars.currentplayer->grabbedrotextrasum = rotextrasum; g_Vars.currentplayer->grabbedposextrasum.x = posextrasum.x; g_Vars.currentplayer->grabbedposextrasum.y = posextrasum.y; g_Vars.currentplayer->grabbedposextrasum.z = posextrasum.z; } } } return cdresult; } bool bgrabCalculateNewPositiontWithPush(struct coord *delta, f32 angle, bool arg2) { s32 result = bgrabCalculateNewPosition(delta, angle, arg2); if (result != CDRESULT_NOCOLLISION) { struct prop *obstacle = cdGetObstacle(); if (obstacle && g_Vars.lvupdate240 > 0) { if (obstacle->type == PROPTYPE_CHR) { // empty } else if (obstacle->type == PROPTYPE_PLAYER) { // empty } else if (obstacle->type == PROPTYPE_OBJ) { struct defaultobj *obj = obstacle->obj; if ((obj->hidden & OBJHFLAG_MOUNTED) == 0 && (obj->hidden & OBJHFLAG_GRABBED) == 0 && (obj->flags3 & OBJFLAG3_PUSHABLE)) { bool canpush = true; g_Vars.currentplayer->speedmaxtime60 = 0; if ((obj->hidden & OBJHFLAG_PROJECTILE) && (obj->projectile->flags & PROJECTILEFLAG_00001000)) { canpush = false; } if (canpush) { bgrab0f0ccbf0(delta, angle, obj); if ((obj->hidden & OBJHFLAG_PROJECTILE) && (obj->projectile->flags & PROJECTILEFLAG_SLIDING)) { s32 someint; bool embedded = false; someint = projectileTick(obj, &embedded); if ((obj->hidden & OBJHFLAG_PROJECTILE)) { obj->projectile->flags |= PROJECTILEFLAG_00001000; if (someint) { obj->projectile->flags |= PROJECTILEFLAG_00002000; } else { obj->projectile->flags &= ~PROJECTILEFLAG_00002000; } } if (someint) { result = bgrabCalculateNewPosition(delta, angle, arg2); } } } } } } } return result; } bool bgrab0f0cdb04(f32 angle, bool arg2) { struct coord coord = {0, 0, 0}; bool result; g_Vars.currentplayer->grabbeddoextra = true; result = bgrabCalculateNewPositiontWithPush(&coord, angle, arg2); g_Vars.currentplayer->grabbeddoextra = false; return result; } bool bgrab0f0cdb68(f32 angle) { struct coord spa4; struct coord sp98; struct coord sp8c; struct coord sp80; f32 sp7c; f32 sp78; f32 f2; f32 f20; f32 f22; s32 i; f32 f0; f32 sp60 = -1.0f; struct coord sp54; f32 f12; f32 radius; f32 ymax; f32 ymin; #if VERSION >= VERSION_NTSC_1_0 cd00024e4c(&spa4, &sp98, 678, "bondgrab.c"); #else cd00024e4c(&spa4, &sp98, 674, "bondgrab.c"); #endif sp7c = sp98.f[0] - spa4.f[0]; sp78 = sp98.f[2] - spa4.f[2]; if (sp7c == 0.0f && sp78 == 0.0f) { sp78 = 1.0f; } else { f12 = 1.0f / sqrtf(sp7c * sp7c + sp78 * sp78); sp7c = sp7c * f12; sp78 = sp78 * f12; } f20 = sp78; f22 = -sp7c; if ((f20 * (g_Vars.currentplayer->prop->pos.x - spa4.f[0]) + f22 * (g_Vars.currentplayer->prop->pos.z - spa4.f[2])) < 0.0f) { f20 = -f20; f22 = -f22; } if (var8005f034) { for (i = 0; i < var8009a918.header.numvertices; i++) { f0 = (var8009a918.vertices[i][0] - spa4.f[0]) * f20 + (var8009a918.vertices[i][1] - spa4.f[2]) * f22; if (f0 < 0.0f) { f0 = -f0; if (f0 > sp60) { sp60 = f0; } } } } else { if (cd00025364(&sp8c, &sp80)) { f32 f0 = (sp8c.f[0] - spa4.f[0]) * f20 + f22 * (sp8c.f[2] - spa4.f[2]); f32 f16 = (sp80.f[0] - spa4.f[0]) * f20 + f22 * (sp80.f[2] - spa4.f[2]); if (f16 < f0) { f0 = f16; } if (f0 < 0.0f) { sp60 = -f0; } } else if (var80070e80 != 0) { if (g_Vars.currentplayer->grabbedprop->type == PROPTYPE_OBJ) { if (g_Vars.currentplayer->grabbedprop->obj->flags3 & OBJFLAG3_GEOCYL) { objGetBbox(g_Vars.currentplayer->grabbedprop, &radius, &ymax, &ymin); f0 = (var8009de78.f[0] - spa4.f[0]) * f20 + (var8009de78.f[2] - spa4.f[2]) * f22; f0 -= radius; if (f0 < 0.0f) { sp60 = -f0; } } } } } f2 = sinf(angle) * 400.0f; if (f2 < 0.0f) { f2 = -f2; } if (f2 < sp60) { sp60 = f2; } if (sp60 >= 0.0f) { sp54.x = sp60 * f20 * 1.01f; sp54.y = 0.0f; sp54.z = sp60 * f22 * 1.01f; bgrab0f0ce0bc(&sp54); return bgrab0f0cdb04(angle, true); } return false; } void bgrab0f0cdef0(void) { if (g_Vars.lvupdate240 > 0) { f32 angle = g_Vars.currentplayer->speedtheta * g_Vars.lvupdate240freal * 0.017450513318181f * 3.5f; if (bgrab0f0cdb04(angle, true) == 0) { bgrab0f0cdb68(angle); } } } bool bgrab0f0cdf64(struct coord *delta, struct coord *arg1, struct coord *arg2) { bool result = bgrabCalculateNewPositiontWithPush(delta, 0, true); if (!result) { #if VERSION >= VERSION_NTSC_1_0 cd00024e4c(arg1, arg2, 815, "bondgrab.c"); #else cd00024e4c(arg1, arg2, 811, "bondgrab.c"); #endif } return result; } s32 bgrab0f0cdfbc(struct coord *delta, struct coord *arg1, struct coord *arg2) { if (arg1->f[0] != arg2->f[0] || arg1->f[2] != arg2->f[2]) { f32 tmp; struct coord sp30; struct coord sp24; sp30.x = arg2->x - arg1->x; sp30.z = arg2->z - arg1->z; tmp = 1.0f / sqrtf(sp30.f[0] * sp30.f[0] + sp30.f[2] * sp30.f[2]); sp30.x *= tmp; sp30.z *= tmp; tmp = delta->f[0] * sp30.f[0] + delta->f[2] * sp30.f[2]; sp24.x = sp30.x * tmp; sp24.y = 0; sp24.z = sp30.z * tmp; return bgrabCalculateNewPositiontWithPush(&sp24, 0, true); } return -1; } void bgrab0f0ce0bc(struct coord *arg0) { struct coord a; struct coord b; s32 value = bgrab0f0cdf64(arg0, &a, &b); if (value == 0) { value = bgrab0f0cdfbc(arg0, &a, &b); if (value <= 0) { value = 1; } } if (value) { // empty } } void bgrabUpdatePrevPos(void) { g_Vars.currentplayer->bondprevpos.x = g_Vars.currentplayer->prop->pos.x; g_Vars.currentplayer->bondprevpos.y = g_Vars.currentplayer->prop->pos.y; g_Vars.currentplayer->bondprevpos.z = g_Vars.currentplayer->prop->pos.z; g_Vars.currentplayer->bondprevtheta = g_Vars.currentplayer->vv_theta; g_Vars.currentplayer->grabbedprevpos.x = g_Vars.currentplayer->grabbedprop->pos.x; g_Vars.currentplayer->grabbedprevpos.y = g_Vars.currentplayer->grabbedprop->pos.y; g_Vars.currentplayer->grabbedprevpos.z = g_Vars.currentplayer->grabbedprop->pos.z; } void bgrab0f0ce178(void) { func0f069c70(g_Vars.currentplayer->grabbedprop->obj, 0, 1); } void bgrabUpdateVertical(void) { f32 stack; s32 i; f32 tmp; s32 inlift; struct prop *lift = NULL; f32 dist; f32 f14; f32 fVar3; f32 f0; f14 = cdFindGroundY(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->bond2.radius, g_Vars.currentplayer->prop->rooms, &g_Vars.currentplayer->floorcol, &g_Vars.currentplayer->floortype, &g_Vars.currentplayer->floorflags, &g_Vars.currentplayer->floorroom, &inlift, &lift); if (f14 < -30000) { f14 = -30000; } if (g_Vars.currentplayer->inlift && inlift) { if (g_Vars.currentplayer->lift == lift) { dist = g_Vars.currentplayer->liftground - g_Vars.currentplayer->vv_manground; if (dist < 1.0f && dist > -1.0f) { f0 = f14 - g_Vars.currentplayer->vv_ground; g_Vars.currentplayer->vv_ground += f0; g_Vars.currentplayer->vv_manground += f0; g_Vars.currentplayer->sumground = g_Vars.currentplayer->vv_manground / (PAL ? 0.054400026798248f : 0.045499980449677f); } } } else { lift = NULL; } g_Vars.currentplayer->inlift = inlift; if (inlift) { g_Vars.currentplayer->liftground = f14; } g_Vars.currentplayer->lift = lift; g_Vars.currentplayer->vv_ground = f14; g_Vars.currentplayer->vv_height = (g_Vars.currentplayer->headpos.y / g_Vars.currentplayer->standheight) * g_Vars.currentplayer->vv_eyeheight; fVar3 = g_Vars.currentplayer->vv_manground / (PAL ? 0.054400026798248f : 0.045499980449677f); for (i = 0; i < g_Vars.lvupdate240; i++) { fVar3 = (PAL ? 0.94559997320175f : 0.9545f) * fVar3 + g_Vars.currentplayer->vv_ground; } f0 = g_Vars.currentplayer->vv_height; if (f0 < 30) { f0 = 30; } tmp = fVar3 * (PAL ? 0.054400026798248f : 0.045499980449677f) + f0 - g_Vars.currentplayer->prop->pos.y; #if VERSION >= VERSION_NTSC_1_0 if (g_Vars.currentplayer->prop->pos.y + tmp < g_Vars.currentplayer->vv_ground + 10.0f) { tmp = g_Vars.currentplayer->vv_ground + 10.0f - g_Vars.currentplayer->prop->pos.y; } #endif if (bgrabTryMoveUpwards(tmp)) { g_Vars.currentplayer->sumground = fVar3; g_Vars.currentplayer->vv_manground = fVar3 * (PAL ? 0.054400026798248f : 0.045499980449677f); } if ((g_Vars.currentplayer->floorflags & GEOFLAG_DIE) && g_Vars.currentplayer->vv_manground - 20.0f < g_Vars.currentplayer->vv_ground) { playerDie(true); } } void bgrabHandleActivate(void) { if (currentPlayerTryMountHoverbike(g_Vars.currentplayer->grabbedprop)) { g_Vars.currentplayer->bondactivateorreload = 0; } else { g_Vars.currentplayer->bondactivateorreload = 0; bmoveSetMode(MOVEMODE_WALK); } } void bgrabUpdateSpeedSideways(f32 targetspeed, f32 accelspeed, s32 mult) { if (targetspeed < g_Vars.currentplayer->speedstrafe) { g_Vars.currentplayer->speedstrafe -= PALUPF(accelspeed * mult); if (g_Vars.currentplayer->speedstrafe < targetspeed) { g_Vars.currentplayer->speedstrafe = targetspeed; } } else if (g_Vars.currentplayer->speedstrafe < targetspeed) { g_Vars.currentplayer->speedstrafe += PALUPF(accelspeed * mult); if (g_Vars.currentplayer->speedstrafe > targetspeed) { g_Vars.currentplayer->speedstrafe = targetspeed; } } g_Vars.currentplayer->speedsideways = g_Vars.currentplayer->speedstrafe; } void bgrabUpdateSpeedForwards(f32 target, f32 speed) { if (g_Vars.currentplayer->speedgo < target) { g_Vars.currentplayer->speedgo += speed * g_Vars.lvupdate240freal; if (g_Vars.currentplayer->speedgo > target) { g_Vars.currentplayer->speedgo = target; } } else if (g_Vars.currentplayer->speedgo > target) { g_Vars.currentplayer->speedgo -= speed * g_Vars.lvupdate240freal; if (g_Vars.currentplayer->speedgo < target) { g_Vars.currentplayer->speedgo = target; } } g_Vars.currentplayer->speedforwards = g_Vars.currentplayer->speedgo; } void bgrabApplyMoveData(struct movedata *data) { // Sideways if (data->digitalstepleft) { bgrabUpdateSpeedSideways(-1, 0.2f / 3.0f, data->digitalstepleft); } else if (data->digitalstepright) { bgrabUpdateSpeedSideways(1, 0.2f / 3.0f, data->digitalstepright); } else if (data->unk14 == 0) { bgrabUpdateSpeedSideways(0, 0.2f / 3.0f, g_Vars.lvupdate240_60); } if (data->unk14) { bgrabUpdateSpeedSideways(data->analogstrafe * 0.014285714365542f, 0.2f / 3.0f, g_Vars.lvupdate240_60); } // Forward/back if (data->digitalstepforward) { bgrabUpdateSpeedForwards(1, 0.2f / 3.0f); g_Vars.currentplayer->speedmaxtime60 += g_Vars.lvupdate240_60; } else if (data->digitalstepback) { bgrabUpdateSpeedForwards(-1, 0.2f / 3.0f); } else if (data->canlookahead == false) { bgrabUpdateSpeedForwards(0, 0.2f / 3.0f); } if (data->canlookahead) { bgrabUpdateSpeedForwards(data->analogwalk * 0.014285714365542f, 0.2f / 3.0f); if (data->analogwalk > 60) { g_Vars.currentplayer->speedmaxtime60 += g_Vars.lvupdate240_60; } else { g_Vars.currentplayer->speedmaxtime60 = 0; } } if (g_Vars.currentplayer->speedforwards > 1) { g_Vars.currentplayer->speedforwards = 1; } if (g_Vars.currentplayer->speedforwards < -1) { g_Vars.currentplayer->speedforwards = -1; } if (g_Vars.currentplayer->speedsideways > 1) { g_Vars.currentplayer->speedsideways = 1; } if (g_Vars.currentplayer->speedsideways < -1) { g_Vars.currentplayer->speedsideways = -1; } g_Vars.currentplayer->speedforwards *= 1.08f; g_Vars.currentplayer->speedforwards *= g_Vars.currentplayer->speedboost; if (data->canlookahead == false && data->digitalstepforward == false) { g_Vars.currentplayer->speedmaxtime60 = 0; } } void bgrabUpdateSpeedTheta(void) { f32 mult = (PAL ? 0.97519999742508f : 0.98470002412796f); f32 speedtheta = g_Vars.currentplayer->speedtheta * 0.75f; s32 i; for (i = 0; i < g_Vars.lvupdate240; i++) { g_Vars.currentplayer->bondgrabthetaspeedsum = g_Vars.currentplayer->bondgrabthetaspeedsum * mult + speedtheta; } g_Vars.currentplayer->speedtheta = g_Vars.currentplayer->bondgrabthetaspeedsum * (PAL ? 0.024800002574921f : 0.01529997587204f); } void bgrab0f0ce924(void) { f32 mult; f32 sp88; f32 sp84; f32 sp80; struct coord sp74 = {0, 0, 0}; f32 sp70; f32 sp6c; f32 speedforwards; f32 speedsideways; f32 speedtheta; f32 maxspeed; f32 xdelta; f32 zdelta; f32 sp50; f32 sp4c; f32 sp48; f32 sp44; f32 sp40; f32 sp3c; f32 sp38; f32 breathing; if (g_Vars.lvupdate240 > 0) { bmove0f0cba88(&sp70, &sp6c, &g_Vars.currentplayer->bondshotspeed, g_Vars.currentplayer->vv_sintheta, g_Vars.currentplayer->vv_costheta); g_Vars.currentplayer->speedforwards += sp70; g_Vars.currentplayer->speedsideways += sp6c; mult = var80075c00[1].unk0c * 0.5f * g_Vars.lvupdate240freal; sp88 = mult * g_Vars.currentplayer->speedsideways; speedsideways = g_Vars.currentplayer->speedsideways * 0.8f; speedforwards = g_Vars.currentplayer->speedforwards; speedtheta = g_Vars.currentplayer->speedtheta * 0.8f; if (speedsideways < 0.0f) { speedsideways = -speedsideways; } if (speedforwards < 0.0f) { speedforwards = -speedforwards; } if (speedtheta < 0.0f) { speedtheta = -speedtheta; } maxspeed = speedforwards; if (speedsideways > maxspeed) { maxspeed = speedsideways; } if (speedtheta > maxspeed) { maxspeed = speedtheta; } if (maxspeed >= 0.75f) { g_Vars.currentplayer->bondbreathing += (maxspeed - 0.75f) * g_Vars.lvupdate240freal / 900.0f; } else { g_Vars.currentplayer->bondbreathing -= (0.75f - maxspeed) * g_Vars.lvupdate240freal / 2700.0f; } if (g_Vars.currentplayer->bondbreathing < 0.0f) { g_Vars.currentplayer->bondbreathing = 0.0f; } else if (g_Vars.currentplayer->bondbreathing > 1.0f) { g_Vars.currentplayer->bondbreathing = 1.0f; } bmove0f0cc654(maxspeed, g_Vars.currentplayer->speedforwards, sp88); g_Vars.currentplayer->gunspeed = maxspeed; sp84 = g_Vars.currentplayer->headpos.x; sp80 = g_Vars.currentplayer->headpos.z; #if VERSION >= VERSION_NTSC_1_0 if (cheatIsActive(CHEAT_SMALLJO)) { sp84 *= 0.4f; sp80 *= 0.4f; } #endif sp74.x += (sp80 * g_Vars.currentplayer->bond2.unk00.f[0] - sp84 * g_Vars.currentplayer->bond2.unk00.f[2]) * g_Vars.lvupdate240freal; sp74.z += (sp80 * g_Vars.currentplayer->bond2.unk00.f[2] + sp84 * g_Vars.currentplayer->bond2.unk00.f[0]) * g_Vars.lvupdate240freal; bmoveUpdateMoveInitSpeed(&sp74); if (debugIsTurboModeEnabled()) { sp74.x += (g_Vars.currentplayer->bond2.unk00.f[0] * g_Vars.currentplayer->speedforwards - (g_Vars.currentplayer->bond2.unk00.f[2] * g_Vars.currentplayer->speedsideways)) * g_Vars.lvupdate240freal * 10.0f; sp74.z += (g_Vars.currentplayer->bond2.unk00.f[2] * g_Vars.currentplayer->speedforwards + (g_Vars.currentplayer->bond2.unk00.f[0] * g_Vars.currentplayer->speedsideways)) * g_Vars.lvupdate240freal * 10.0f; } bgrab0f0ce0bc(&sp74); xdelta = g_Vars.currentplayer->prop->pos.f[0] - g_Vars.currentplayer->bondprevpos.f[0]; zdelta = g_Vars.currentplayer->prop->pos.f[2] - g_Vars.currentplayer->bondprevpos.f[2]; sp50 = -xdelta * g_Vars.currentplayer->bond2.unk00.f[2] + zdelta * g_Vars.currentplayer->bond2.unk00.f[0]; sp4c = xdelta * g_Vars.currentplayer->bond2.unk00.f[0] + zdelta * g_Vars.currentplayer->bond2.unk00.f[2]; sp48 = -sp74.f[0] * g_Vars.currentplayer->bond2.unk00.f[2] + sp74.f[2] * g_Vars.currentplayer->bond2.unk00.f[0]; sp44 = sp74.f[0] * g_Vars.currentplayer->bond2.unk00.f[0] + sp74.f[2] * g_Vars.currentplayer->bond2.unk00.f[2]; if (sp48 != 0.0f) { if (g_Vars.currentplayer->speedstrafe * sp48 > 0.0f) { sp50 /= sp48; if (sp50 <= 0.0f) { g_Vars.currentplayer->speedstrafe = 0.0f; } else if (sp50 < 1.0f) { g_Vars.currentplayer->speedstrafe *= sp50; } } } if (sp44 != 0.0f) { if (g_Vars.currentplayer->speedgo * sp44 > 0.0f) { sp4c /= sp44; if (sp4c <= 0.0f) { g_Vars.currentplayer->speedgo = 0.0f; } else if (sp4c < 1.0f) { g_Vars.currentplayer->speedgo *= sp4c; } } } sp40 = g_Vars.currentplayer->speedtheta; sp3c = g_Vars.currentplayer->speedverta / 0.7f; sp38 = g_Vars.currentplayer->gunspeed; breathing = bheadGetBreathingValue(); if (sp3c > 1.0f) { sp3c = 1.0f; } else if (sp3c < -1.0f) { sp3c = -1.0f; } if (g_Vars.currentplayer->headanim == 1) { breathing *= 1.2f; } bgun0f09d8dc(breathing, sp38, sp3c, sp40, 0.0f); bgunSetAdjustPos(g_Vars.currentplayer->vv_verta360 * 0.017450513f); } } void bgrabTick(void) { bgrabUpdatePrevPos(); bgrab0f0cdef0(); bmoveUpdateVerta(); bgrab0f0ce924(); bgrab0f0ce178(); bgrabUpdateVertical(); #if VERSION >= VERSION_NTSC_1_0 { s32 i; for (i = 0; g_Vars.currentplayer->prop->rooms[i] != -1; i++) { if (g_Vars.currentplayer->prop->rooms[i] == g_Vars.currentplayer->floorroom) { propDeregisterRooms(g_Vars.currentplayer->prop); g_Vars.currentplayer->prop->rooms[0] = g_Vars.currentplayer->floorroom; g_Vars.currentplayer->prop->rooms[1] = -1; break; } } } #endif { struct defaultobj *obj = g_Vars.currentplayer->grabbedprop->obj; struct hov *hov = NULL; if (obj->type == OBJTYPE_HOVERPROP) { struct hoverpropobj *hoverprop = (struct hoverpropobj *)g_Vars.currentplayer->grabbedprop->obj; hov = &hoverprop->hov; } else if (obj->type == OBJTYPE_HOVERBIKE) { struct hoverbikeobj *hoverbike = (struct hoverbikeobj *)g_Vars.currentplayer->grabbedprop->obj; hov = &hoverbike->hov; } if (hov) { hovTick(obj, hov); } bmoveUpdateRooms(g_Vars.currentplayer); objectiveCheckRoomEntered(g_Vars.currentplayer->prop->rooms[0]); bmove0f0cc19c(&g_Vars.currentplayer->prop->pos); playerUpdatePerimInfo(); doorsCheckAutomatic(); if (g_Vars.currentplayer->grabbedprop) { // Determine if the grabbed prop should be force released f32 ydiff = g_Vars.currentplayer->grabbedprop->pos.y - objGetHov04(g_Vars.currentplayer->grabbedprop->obj) - g_Vars.currentplayer->vv_manground; struct prop *grabbedprop = g_Vars.currentplayer->grabbedprop; propSetPerimEnabled(g_Vars.currentplayer->prop, false); propSetPerimEnabled(grabbedprop, false); if (g_Vars.currentplayer->vv_ground <= -30000 || ydiff < -100 || ydiff > 100 || g_Vars.currentplayer->vv_ground < g_Vars.currentplayer->vv_manground - 50 || !cdHasLineOfSight(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->prop->rooms, &g_Vars.currentplayer->grabbedprop->pos, g_Vars.currentplayer->grabbedprop->rooms, CDTYPE_ALL, 12)) { bmoveSetMode(MOVEMODE_WALK); } propSetPerimEnabled(g_Vars.currentplayer->prop, true); propSetPerimEnabled(grabbedprop, true); } } }