Migrate projectile to a class

FossilOrigin-Name: d3b4b2d476d809f7ab00502eed47614c949264690b3eccc7a96c73687d0f05bf
This commit is contained in:
Jonathan Schleifer 2025-03-09 11:24:01 +00:00
parent dae9d5553c
commit 410e244ed6
9 changed files with 97 additions and 82 deletions

11
src/Projectile.h Normal file
View file

@ -0,0 +1,11 @@
#import <ObjFW/ObjFW.h>
typedef struct dynent dynent;
@interface Projectile: OFObject
@property (nonatomic) OFVector3D o, to;
@property (nonatomic) float speed;
@property (nonatomic) dynent *owner;
@property (nonatomic) int gun;
@property (nonatomic) bool inuse, local;
@end

4
src/Projectile.m Normal file
View file

@ -0,0 +1,4 @@
#import "Projectile.h"
@implementation Projectile
@end

View file

@ -9,6 +9,7 @@ executable('client',
'MapModelInfo.m',
'Menu.m',
'MenuItem.m',
'Projectile.m',
'Variable.mm',
'client.mm',
'clientextras.mm',

View file

@ -125,8 +125,8 @@ extern entity *newentity(
// worldlight
extern void calclight();
extern void dodynlight(
OFVector3D &vold, OFVector3D &v, int reach, int strength, dynent *owner);
extern void dodynlight(const OFVector3D &vold, const OFVector3D &v, int reach,
int strength, dynent *owner);
extern void cleardlights();
extern block *blockcopy(block &b);
extern void blockpaste(block &b);
@ -166,7 +166,7 @@ extern void line(int x1, int y1, float z1, int x2, int y2, float z2);
extern void box(block &b, float z1, float z2, float z3, float z4);
extern void dot(int x, int y, float z);
extern void linestyle(float width, int r, int g, int b);
extern void newsphere(OFVector3D &o, float max, int type);
extern void newsphere(const OFVector3D &o, float max, int type);
extern void renderspheres(int time);
extern void gl_drawhud(
int w, int h, int curfps, int nquads, int curvert, bool underwater);
@ -176,7 +176,7 @@ extern void damageblend(int n);
// renderparticles
extern void setorient(OFVector3D &r, OFVector3D &u);
extern void particle_splash(int type, int num, int fade, OFVector3D &p);
extern void particle_splash(int type, int num, int fade, const OFVector3D &p);
extern void particle_trail(
int type, int fade, OFVector3D &from, OFVector3D &to);
extern void render_particles(int time);
@ -202,7 +202,7 @@ extern void setentphysics(int mml, int mmr);
extern void physicsframe();
// sound
extern void playsound(int n, OFVector3D *loc = 0);
extern void playsound(int n, const OFVector3D *loc = NULL);
extern void playsoundc(int n);
extern void initsound();
extern void cleansound();

View file

@ -89,7 +89,7 @@ sphere spheres[MAXSPHERES], *slist = NULL, *sempty = NULL;
bool sinit = false;
void
newsphere(OFVector3D &o, float max, int type)
newsphere(const OFVector3D &o, float max, int type)
{
if (!sinit) {
loopi(MAXSPHERES)

View file

@ -15,8 +15,8 @@ bool parinit = false;
VARP(maxparticles, 100, 2000, MAXPARTICLES - 500);
void
newparticle(OFVector3D &o, OFVector3D &d, int fade, int type)
static void
newparticle(const OFVector3D &o, const OFVector3D &d, int fade, int type)
{
if (!parinit) {
loopi(MAXPARTICLES)
@ -133,7 +133,7 @@ render_particles(int time)
}
void
particle_splash(int type, int num, int fade, OFVector3D &p)
particle_splash(int type, int num, int fade, const OFVector3D &p)
{
loopi(num)
{
@ -144,8 +144,7 @@ particle_splash(int type, int num, int fade, OFVector3D &p)
y = rnd(radius * 2) - radius;
z = rnd(radius * 2) - radius;
} while (x * x + y * y + z * z > radius * radius);
OFVector3D d = OFMakeVector3D(x, y, z);
newparticle(p, d, rnd(fade * 3), type);
newparticle(p, OFMakeVector3D(x, y, z), rnd(fade * 3), type);
}
}

View file

@ -92,14 +92,16 @@ music(OFString *name)
IRIByAppendingPathComponent:path];
#ifdef USE_MIXER
if (mod = Mix_LoadMUS(
IRI.fileSystemRepresentation.UTF8String)) {
if ((mod = Mix_LoadMUS(
IRI.fileSystemRepresentation.UTF8String)) !=
NULL) {
Mix_PlayMusic(mod, -1);
Mix_VolumeMusic((musicvol * MAXVOL) / 255);
}
#else
if (mod = FMUSIC_LoadSong(
IRI.fileSystemRepresentation.UTF8String)) {
if ((mod = FMUSIC_LoadSong(
IRI.fileSystemRepresentation.UTF8String)) !=
NULL) {
FMUSIC_PlaySong(mod);
FMUSIC_SetMasterVolume(mod, musicvol);
} else if (stream = FSOUND_Stream_Open(
@ -166,8 +168,8 @@ cleansound()
VAR(stereo, 0, 1, 1);
void
updatechanvol(int chan, OFVector3D *loc)
static void
updatechanvol(int chan, const OFVector3D *loc)
{
int vol = soundvol, pan = 255 / 2;
if (loc) {
@ -194,8 +196,8 @@ updatechanvol(int chan, OFVector3D *loc)
#endif
}
void
newsoundloc(int chan, OFVector3D *loc)
static void
newsoundloc(int chan, const OFVector3D *loc)
{
assert(chan >= 0 && chan < MAXCHAN);
soundlocs[chan].loc = *loc;
@ -230,7 +232,7 @@ playsoundc(int n)
int soundsatonce = 0, lastsoundmillis = 0;
void
playsound(int n, OFVector3D *loc)
playsound(int n, const OFVector3D *loc)
{
if (nosound)
return;

View file

@ -2,17 +2,17 @@
#include "cube.h"
struct guninfo {
short sound, attackdelay, damage, projspeed, part, kickamount;
OFString *name;
};
#import "Projectile.h"
static const int MONSTERDAMAGEFACTOR = 4;
static const int SGRAYS = 20;
static const float SGSPREAD = 2;
static OFVector3D sg[SGRAYS];
static const guninfo guns[NUMGUNS] = {
static const struct {
short sound, attackdelay, damage, projspeed, part, kickamount;
OFString *name;
} guns[NUMGUNS] = {
{ S_PUNCH1, 250, 50, 0, 0, 1, @"fist" },
{ S_SG, 1400, 10, 0, 0, 20, @"shotgun" }, // *SGRAYS
{ S_CG, 100, 30, 0, 0, 7, @"chaingun" },
@ -83,11 +83,12 @@ createrays(OFVector3D &from,
}
}
// if lineseg hits entity bounding box
bool
intersect(dynent *d, OFVector3D &from,
OFVector3D &to) // if lineseg hits entity bounding box
intersect(dynent *d, const OFVector3D &from, const OFVector3D &to)
{
OFVector3D v = to, w = d->o, *p;
OFVector3D v = to, w = d->o;
const OFVector3D *p;
vsub(v, from);
vsub(w, from);
float c1 = dotprod(w, v);
@ -128,37 +129,33 @@ playerincrosshair()
return nil;
}
const int MAXPROJ = 100;
struct projectile {
OFVector3D o, to;
float speed;
dynent *owner;
int gun;
bool inuse, local;
} projs[MAXPROJ];
static const size_t MAXPROJ = 100;
static Projectile *projs[MAXPROJ];
void
projreset()
{
loopi(MAXPROJ) projs[i].inuse = false;
for (size_t i = 0; i < MAXPROJ; i++)
projs[i].inuse = false;
}
void
newprojectile(OFVector3D &from, OFVector3D &to, float speed, bool local,
dynent *owner, int gun)
{
loopi(MAXPROJ)
{
projectile *p = &projs[i];
if (p->inuse)
for (size_t i = 0; i < MAXPROJ; i++) {
Projectile *p = projs[i];
if (p.inuse)
continue;
p->inuse = true;
p->o = from;
p->to = to;
p->speed = speed;
p->local = local;
p->owner = owner;
p->gun = gun;
p.inuse = true;
p.o = from;
p.to = to;
p.speed = speed;
p.local = local;
p.owner = owner;
p.gun = gun;
return;
}
}
@ -181,8 +178,8 @@ hit(int target, int damage, dynent *d, dynent *at)
const float RL_RADIUS = 5;
const float RL_DAMRAD = 7; // hack
void
radialeffect(dynent *o, OFVector3D &v, int cn, int qdam, dynent *at)
static void
radialeffect(dynent *o, const OFVector3D &v, int cn, int qdam, dynent *at)
{
if (o->state != CS_ALIVE)
return;
@ -199,21 +196,21 @@ radialeffect(dynent *o, OFVector3D &v, int cn, int qdam, dynent *at)
}
void
splash(projectile *p, OFVector3D &v, OFVector3D &vold, int notthisplayer,
int notthismonster, int qdam)
splash(Projectile *p, const OFVector3D &v, const OFVector3D &vold,
int notthisplayer, int notthismonster, int qdam)
{
particle_splash(0, 50, 300, v);
p->inuse = false;
if (p->gun != GUN_RL) {
p.inuse = false;
if (p.gun != GUN_RL) {
playsound(S_FEXPLODE, &v);
// no push?
} else {
playsound(S_RLHIT, &v);
newsphere(v, RL_RADIUS, 0);
dodynlight(vold, v, 0, 0, p->owner);
if (!p->local)
dodynlight(vold, v, 0, 0, p.owner);
if (!p.local)
return;
radialeffect(player1, v, -1, qdam, p->owner);
radialeffect(player1, v, -1, qdam, p.owner);
loopv(players)
{
if (i == notthisplayer)
@ -221,42 +218,43 @@ splash(projectile *p, OFVector3D &v, OFVector3D &vold, int notthisplayer,
dynent *o = players[i];
if (!o)
continue;
radialeffect(o, v, i, qdam, p->owner);
radialeffect(o, v, i, qdam, p.owner);
}
dvector &mv = getmonsters();
loopv(mv) if (i != notthismonster)
radialeffect(mv[i], v, i, qdam, p->owner);
radialeffect(mv[i], v, i, qdam, p.owner);
}
}
inline void
projdamage(dynent *o, projectile *p, OFVector3D &v, int i, int im, int qdam)
projdamage(dynent *o, Projectile *p, OFVector3D &v, int i, int im, int qdam)
{
if (o->state != CS_ALIVE)
return;
if (intersect(o, p->o, v)) {
splash(p, v, p->o, i, im, qdam);
hit(i, qdam, o, p->owner);
if (intersect(o, p.o, v)) {
splash(p, v, p.o, i, im, qdam);
hit(i, qdam, o, p.owner);
}
}
void
moveprojectiles(float time)
{
loopi(MAXPROJ)
{
projectile *p = &projs[i];
if (!p->inuse)
for (size_t i = 0; i < MAXPROJ; i++) {
Projectile *p = projs[i];
if (!p.inuse)
continue;
int qdam = guns[p->gun].damage * (p->owner->quadmillis ? 4 : 1);
if (p->owner->monsterstate)
int qdam = guns[p.gun].damage * (p.owner->quadmillis ? 4 : 1);
if (p.owner->monsterstate)
qdam /= MONSTERDAMAGEFACTOR;
vdist(dist, v, p->o, p->to);
float dtime = dist * 1000 / p->speed;
vdist(dist, v, p.o, p.to);
float dtime = dist * 1000 / p.speed;
if (time > dtime)
dtime = time;
vmul(v, time / dtime);
vadd(v, p->o) if (p->local)
vadd(v, p.o) if (p.local)
{
loopv(players)
{
@ -265,28 +263,28 @@ moveprojectiles(float time)
continue;
projdamage(o, p, v, i, -1, qdam);
}
if (p->owner != player1)
if (p.owner != player1)
projdamage(player1, p, v, -1, -1, qdam);
dvector &mv = getmonsters();
loopv(mv) if (!vreject(mv[i]->o, v, 10.0f) &&
mv[i] != p->owner)
mv[i] != p.owner)
projdamage(mv[i], p, v, -1, i, qdam);
}
if (p->inuse) {
if (p.inuse) {
if (time == dtime)
splash(p, v, p->o, -1, -1, qdam);
splash(p, v, p.o, -1, -1, qdam);
else {
if (p->gun == GUN_RL) {
dodynlight(p->o, v, 0, 255, p->owner);
if (p.gun == GUN_RL) {
dodynlight(p.o, v, 0, 255, p.owner);
particle_splash(5, 2, 200, v);
} else {
particle_splash(1, 1, 200, v);
particle_splash(
guns[p->gun].part, 1, 1, v);
guns[p.gun].part, 1, 1, v);
}
}
}
p->o = v;
p.o = v;
}
}

View file

@ -200,8 +200,8 @@ cleardlights()
}
void
dodynlight(
OFVector3D &vold, OFVector3D &v, int reach, int strength, dynent *owner)
dodynlight(const OFVector3D &vold, const OFVector3D &v, int reach, int strength,
dynent *owner)
{
if (!reach)
reach = dynlight;