From 1d94dbfe1b905b6cf1d058413450519e8d545144 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 31 Dec 2022 13:51:57 +1000 Subject: [PATCH] Reinstate cctv --- src/game/propobj.c | 229 ++++++++++++++++++++++++++++++++++++++++++++- src/game/setup.c | 61 ++++++++++++ src/include/data.h | 2 + 3 files changed, 291 insertions(+), 1 deletion(-) diff --git a/src/game/propobj.c b/src/game/propobj.c index d5024d309..7f5702fb8 100644 --- a/src/game/propobj.c +++ b/src/game/propobj.c @@ -108,6 +108,8 @@ s32 g_EmbedHitPart = 0; u32 g_EmbedSide = 0x00000000; s16 var8006993c[3] = {0}; u32 var80069944 = 0x00000000; +f32 g_CctvWaitScale = 1; +f32 g_CctvDamageRxScale = 1; f32 g_AutogunAccuracyScale = 1; f32 g_AutogunDamageTxScale = 1; f32 g_AutogunDamageRxScale = 1; @@ -7681,6 +7683,227 @@ void escastepTick(struct prop *prop) } } +void cctvTick(struct prop *camprop) +{ + struct cctvobj *camera = (struct cctvobj *)camprop->obj; + struct defaultobj *obj = camprop->obj; + f32 yaw; + struct prop *playerprop; + f32 xdist; + f32 ydist; + f32 zdist; + bool canseeplayer = true; + + // If playing in coop mode, cycle between players in alternating frames + if (g_Vars.coopplayernum >= 0) { + if (g_Vars.lvframenum & 1) { + playerprop = g_Vars.bond->prop; + } else { + playerprop = g_Vars.coop->prop; + } + } else { + playerprop = g_Vars.bond->prop; + } + + // Check distance + xdist = playerprop->pos.x - camprop->pos.x; + ydist = playerprop->pos.y - camprop->pos.y; + zdist = playerprop->pos.z - camprop->pos.z; + + yaw = camera->toleft ? camera->yleft : camera->yright; + + if (camera->maxdist > 0) { + if (xdist * xdist + ydist * ydist + zdist * zdist > camera->maxdist * camera->maxdist) { + canseeplayer = false; + } + } + + if (g_Vars.bondvisible == false + || (obj->flags & OBJFLAG_CAMERA_DISABLED) + || (playerprop->chr->hidden & CHRHFLAG_CLOAKED)) { + canseeplayer = false; + } + + // Check horizontal angle + if (canseeplayer) { + f32 angle = atan2f(xdist, zdist); + f32 yrot = camera->yrot; + f32 finalangle; + + if (yrot < 0) { + yrot += M_BADTAU; + } else if (yrot >= M_BADTAU) { + yrot -= M_BADTAU; + } + + yrot += camera->yzero; + + if (yrot >= M_BADTAU) { + yrot -= M_BADTAU; + } + + finalangle = angle - yrot; + + if (angle < yrot) { + finalangle += M_BADTAU; + } + + finalangle -= M_BADPI; + + if (finalangle < 0) { + finalangle += M_BADTAU; + } + + if (finalangle > M_BADPI) { + finalangle -= M_BADTAU; + } + + if (finalangle > 0.7852731347084f || finalangle < -0.7852731347084f) { + canseeplayer = false; + } + } + + // Check vertical angle + if (canseeplayer) { + f32 angle = atan2f(ydist, sqrtf(xdist * xdist + zdist * zdist)); + f32 finalangle = angle - camera->xzero; + + if (angle < camera->xzero) { + finalangle = angle - camera->xzero + M_BADTAU; + } + + if (finalangle > M_BADTAU) { + finalangle -= M_BADTAU; + } + + if (finalangle > M_BADPI) { + finalangle -= M_BADTAU; + } + + if (finalangle); + + if (finalangle > 0.7852731347084f || finalangle < -0.7852731347084f) { + canseeplayer = false; + } + } + + // Check line of sight + if (canseeplayer) { + playerSetPerimEnabled(playerprop, false); + + if (!cdTestLos05(&camprop->pos, camprop->rooms, &playerprop->pos, playerprop->rooms, + CDTYPE_OBJS | CDTYPE_DOORS | CDTYPE_CHRS | CDTYPE_PATHBLOCKER | CDTYPE_BG | CDTYPE_AIOPAQUE, + GEOFLAG_BLOCK_SIGHT)) { + canseeplayer = false; + } + + playerSetPerimEnabled(playerprop, true); + } + + if (canseeplayer) { + obj->flags |= OBJFLAG_CAMERA_BONDINVIEW; + camera->seebondtime60 += g_Vars.lvupdate60; + + if (g_Vars.coopplayernum >= 0) { + camera->seebondtime60 += g_Vars.lvupdate60; + } + + if (camera->seebondtime60 >= (s32)(TICKS(300) * g_CctvWaitScale)) { + alarmActivate(); + camera->seebondtime60 = 0; + } + } else { + obj->flags &= ~OBJFLAG_CAMERA_BONDINVIEW; + } + + // Update yaw + if (camera->yrot < yaw) { + f32 tmp = camera->yspeed * camera->yspeed * 764.06536865234f; + + if (camera->yrot >= yaw - tmp) { + camera->yspeed -= 0.00065439427271485f * g_Vars.lvupdate60freal; + + if (camera->yspeed < 0.00065439427271485f) { + camera->yspeed = 0.00065439427271485f; + } + } else if (camera->yspeed < camera->ymaxspeed) { + f32 newspeed = camera->yspeed + 0.00065439427271485f * g_Vars.lvupdate60freal; + + if (newspeed > camera->ymaxspeed) { + newspeed = camera->ymaxspeed; + } + + if (camera->yrot < yaw - newspeed * newspeed * 764.06536865234f) { + camera->yspeed = newspeed; + } + } + + camera->yrot += camera->yspeed * g_Vars.lvupdate60freal; + + if (camera->yrot >= yaw) { + camera->yrot = yaw; + camera->toleft = false; + camera->yspeed = 0; + } + } else { + f32 tmp = camera->yspeed * camera->yspeed * 764.06536865234f; + + if (camera->yrot <= yaw + tmp) { + camera->yspeed -= 0.00065439427271485f * g_Vars.lvupdate60freal; + + if (camera->yspeed < 0.00065439427271485f) { + camera->yspeed = 0.00065439427271485f; + } + } else if (camera->yspeed < camera->ymaxspeed) { + f32 newspeed = camera->yspeed + 0.00065439427271485f * g_Vars.lvupdate60freal; + + if (newspeed > camera->ymaxspeed) { + newspeed = camera->ymaxspeed; + } + + if (camera->yrot > yaw + newspeed * newspeed * 764.06536865234f) { + camera->yspeed = newspeed; + } + } + + camera->yrot -= camera->yspeed * g_Vars.lvupdate60freal; + + if (camera->yrot <= yaw) { + camera->yrot = yaw; + camera->toleft = true; + camera->yspeed = 0; + } + } +} + +void cctvInitMatrices(struct prop *prop, Mtxf *mtx) +{ + struct cctvobj *cctv = (struct cctvobj *)prop->obj; + struct model *model = cctv->base.model; + Mtxf *matrices = model->matrices; + union modelrodata *rodata = modelGetPartRodata(model->filedata, MODELPART_CCTV_CASING); + struct coord sp64; + Mtxf sp24; + f32 yrot = cctv->yrot; + + if (yrot < 0) { + yrot += M_BADTAU; + } else if (yrot >= M_BADTAU) { + yrot -= M_BADTAU; + } + + mtx4LoadYRotation(yrot, &sp24); + mtx4MultMtx4(&sp24, &cctv->camrotm, &matrices[1]); + + sp64.x = rodata->position.pos.x; + sp64.y = rodata->position.pos.y; + sp64.z = rodata->position.pos.z; + + mtx4TransformVecInPlace(mtx, &sp64); + mtx4SetTranslation(&sp64, &matrices[1]); + mtx00015be0(camGetWorldToScreenMtxf(), &matrices[1]); +} + void fanTick(struct prop *prop) { struct defaultobj *obj = (struct defaultobj *)prop->obj; @@ -9990,7 +10213,9 @@ void objInitMatrices(struct prop *prop) mtx4SetTranslation(&prop->pos, &mtx); mtx00015be4(camGetWorldToScreenMtxf(), &mtx, obj->model->matrices); - if (obj->type == OBJTYPE_AUTOGUN) { + if (obj->type == OBJTYPE_CCTV) { + cctvInitMatrices(prop, &mtx); + } else if (obj->type == OBJTYPE_AUTOGUN) { autogunInitMatrices(prop, &mtx); } else if (obj->type == OBJTYPE_CHOPPER) { chopperInitMatrices(prop); @@ -10376,6 +10601,8 @@ s32 objTickPlayer(struct prop *prop) if (obj->type == OBJTYPE_DOOR) { doorTick(prop); + } else if (obj->type == OBJTYPE_CCTV && (obj->flags & OBJFLAG_DEACTIVATED) == 0) { + cctvTick(prop); } else if (obj->type == OBJTYPE_FAN) { fanTick(prop); } else if (obj->type == OBJTYPE_AUTOGUN && (obj->flags & OBJFLAG_DEACTIVATED) == 0) { diff --git a/src/game/setup.c b/src/game/setup.c index 1777e58ac..dd2994055 100644 --- a/src/game/setup.c +++ b/src/game/setup.c @@ -272,6 +272,8 @@ void propsReset(void) g_EmbedProp = NULL; g_EmbedHitPart = -1; + g_CctvWaitScale = 1; + g_CctvDamageRxScale = 1; g_AutogunAccuracyScale = 1; g_AutogunDamageTxScale = 1; g_AutogunDamageRxScale = 1; @@ -719,6 +721,60 @@ void setupCreateMine(struct mineobj *mine, s32 cmdindex) } } +void setupCreateCctv(struct cctvobj *cctv, s32 cmdindex) +{ + struct defaultobj *obj = &cctv->base; + + setupCreateObject(obj, cmdindex); + + if (cctv->lookatpadnum >= 0) { + struct coord lenspos; + union modelrodata *lens = modelGetPartRodata(obj->model->filedata, MODELPART_CCTV_CASING); + struct pad *pad; + f32 xdiff; + f32 ydiff; + f32 zdiff; + + pad = &g_Pads[cctv->lookatpadnum]; + + lenspos = lens->position.pos; + + mtx00016208(obj->realrot, &lenspos); + + lenspos.x += obj->prop->pos.x; + lenspos.y += obj->prop->pos.y; + lenspos.z += obj->prop->pos.z; + + xdiff = lenspos.x - pad->pos.x; + ydiff = lenspos.y - pad->pos.y; + zdiff = lenspos.z - pad->pos.z; + + if (ydiff) { + // empty + } + + mtx00016d58(&cctv->camrotm, 0.0f, 0.0f, 0.0f, xdiff, ydiff, zdiff, 0.0f, 1.0f, 0.0f); + mtx00015f04(obj->model->scale, &cctv->camrotm); + + cctv->toleft = 0; + cctv->yleft = *(s32 *)&cctv->yleft * M_BADTAU / 65536.0f; + cctv->yright = *(s32 *)&cctv->yright * M_BADTAU / 65536.0f; + cctv->yspeed = 0.0f; + cctv->ymaxspeed = *(s32 *)&cctv->ymaxspeed * M_BADTAU / 65536.0f; + cctv->maxdist = *(s32 *)&cctv->maxdist; + cctv->yrot = cctv->yleft; + + cctv->yzero = atan2f(xdiff, zdiff); + cctv->xzero = M_BADTAU - atan2f(ydiff, sqrtf(xdiff * xdiff + zdiff * zdiff)); + + if (xdiff || zdiff) { + // empty + } + + cctv->seebondtime60 = 0; + } +} + void setupCreateAutogun(struct autogunobj *autogun, s32 cmdindex) { setupCreateObject(&autogun->base, cmdindex); @@ -1434,6 +1490,11 @@ void setupCreateProps(s32 stagenum) setupCreateKey((struct keyobj *)obj, index); } break; + case OBJTYPE_CCTV: + if (withobjs && (obj->flags2 & diffflag) == 0) { + setupCreateCctv((struct cctvobj *)obj, index); + } + break; case OBJTYPE_AUTOGUN: if (withobjs && (obj->flags2 & diffflag) == 0) { setupCreateAutogun((struct autogunobj *)obj, index); diff --git a/src/include/data.h b/src/include/data.h index 78b5fb4a7..38b3a6319 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -262,6 +262,8 @@ extern struct linksceneryobj *g_LinkedScenery; extern struct blockedpathobj *g_BlockedPaths; extern struct prop *g_EmbedProp; extern s32 g_EmbedHitPart; +extern f32 g_CctvWaitScale; +extern f32 g_CctvDamageRxScale; extern f32 g_AutogunAccuracyScale; extern f32 g_AutogunDamageTxScale; extern f32 g_AutogunDamageRxScale;