Clean up DynamicEntity

FossilOrigin-Name: b787ad5a04fc238a69b9e48b3bdfccde416f636a021eef0d955445b5ab92252b
This commit is contained in:
Jonathan Schleifer 2025-03-22 23:10:13 +00:00
parent fd2b1dddf0
commit a7db00c740
24 changed files with 561 additions and 540 deletions

View file

@ -232,7 +232,7 @@ VARP(minmillis, 0, 5, 1000);
static float fps = 30.0f; static float fps = 30.0f;
fps = (1000.0f / curtime + fps * 50) / 51; fps = (1000.0f / curtime + fps * 50) / 51;
computeraytable(player1.o.x, player1.o.y); computeraytable(player1.origin.x, player1.origin.y);
readdepth(_width, _height); readdepth(_width, _height);
SDL_GL_SwapWindow(_window); SDL_GL_SwapWindow(_window);
extern void updatevol(); extern void updatevol();

View file

@ -4,52 +4,55 @@
@interface DynamicEntity: OFObject <OFCopying> @interface DynamicEntity: OFObject <OFCopying>
@property (class, readonly, nonatomic) size_t serializedSize; @property (class, readonly, nonatomic) size_t serializedSize;
// origin, velocity @property (nonatomic) OFVector3D origin, velocity;
@property (nonatomic) OFVector3D o, vel;
// used as OFVector3D in one place // used as OFVector3D in one place
@property (nonatomic) float yaw, pitch, roll; @property (nonatomic) float yaw, pitch, roll;
// cubes per second, 24 for player // cubes per second, 24 for player
@property (nonatomic) float maxspeed; @property (nonatomic) float maxSpeed;
// from his eyes // from his eyes
@property (nonatomic) bool outsidemap; @property (nonatomic) bool outsideMap;
@property (nonatomic) bool inwater; @property (nonatomic) bool inWater;
@property (nonatomic) bool onfloor, jumpnext; @property (nonatomic) bool onFloor, jumpNext;
@property (nonatomic) int move, strafe; @property (nonatomic) int move, strafe;
// see input code // see input code
@property (nonatomic) bool k_left, k_right, k_up, k_down; @property (nonatomic) bool k_left, k_right, k_up, k_down;
// used for fake gravity // used for fake gravity
@property (nonatomic) int timeinair; @property (nonatomic) int timeInAir;
// bounding box size // bounding box size
@property (nonatomic) float radius, eyeheight, aboveeye; @property (nonatomic) float radius, eyeHeight, aboveEye;
@property (nonatomic) int lastupdate, plag, ping; @property (nonatomic) int lastUpdate, lag, ping;
// sequence id for each respawn, used in damage test // sequence id for each respawn, used in damage test
@property (nonatomic) int lifesequence; @property (nonatomic) int lifeSequence;
// one of CS_* below // one of CS_* below
@property (nonatomic) int state; @property (nonatomic) int state;
@property (nonatomic) int frags; @property (nonatomic) int frags;
@property (nonatomic) int health, armour, armourtype, quadmillis; @property (nonatomic) int health, armour, armourType, quadMillis;
@property (nonatomic) int gunselect, gunwait; @property (nonatomic) int gunSelect, gunWait;
@property (nonatomic) int lastaction, lastattackgun, lastmove; @property (nonatomic) int lastAction, lastAttackGun, lastMove;
@property (nonatomic) bool attacking; @property (nonatomic) bool attacking;
@property (readonly, nonatomic) int *ammo; @property (readonly, nonatomic) int *ammo;
// one of M_* below, M_NONE means human // one of M_* below, M_NONE means human
@property (nonatomic) int monsterstate; @property (nonatomic) int monsterState;
// see monster.cpp // see monster.m
@property (nonatomic) int mtype; @property (nonatomic) int monsterType;
// monster wants to kill this entity // monster wants to kill this entity
@property (nonatomic) DynamicEntity *enemy; @property (nonatomic) DynamicEntity *enemy;
// monster wants to look in this direction // monster wants to look in this direction
@property (nonatomic) float targetyaw; @property (nonatomic) float targetYaw;
// used by physics to signal ai // used by physics to signal ai
@property (nonatomic) bool blocked, moving; @property (nonatomic) bool blocked, moving;
// millis at which transition to another monsterstate takes place // millis at which transition to another monsterstate takes place
@property (nonatomic) int trigger; @property (nonatomic) int trigger;
// delayed attacks // delayed attacks
@property (nonatomic) OFVector3D attacktarget; @property (nonatomic) OFVector3D attackTarget;
// how many times already hit by fellow monster // how many times already hit by fellow monster
@property (nonatomic) int anger; @property (nonatomic) int anger;
@property (copy, nonatomic) OFString *name, *team; @property (copy, nonatomic) OFString *name, *team;
+ (instancetype)entity;
- (OFData *)dataBySerializing; - (OFData *)dataBySerializing;
- (void)setFromSerializedData:(OFData *)data; - (void)setFromSerializedData:(OFData *)data;
- (void)resetMovement;
// reset player state not persistent accross spawns
- (void)resetToSpawnState;
@end @end

View file

@ -3,37 +3,42 @@
#include "cube.h" #include "cube.h"
struct dynent { struct dynent {
OFVector3D o, vel; OFVector3D origin, velocity;
float yaw, pitch, roll; float yaw, pitch, roll;
float maxspeed; float maxSpeed;
bool outsidemap; bool outsideMap;
bool inwater; bool inWater;
bool onfloor, jumpnext; bool onFloor, jumpNext;
int move, strafe; int move, strafe;
bool k_left, k_right, k_up, k_down; bool k_left, k_right, k_up, k_down;
int timeinair; int timeInAir;
float radius, eyeheight, aboveeye; float radius, eyeHeight, aboveEye;
int lastupdate, plag, ping; int lastUpdate, lag, ping;
int lifesequence; int lifeSequence;
int state; int state;
int frags; int frags;
int health, armour, armourtype, quadmillis; int health, armour, armourType, quadMillis;
int gunselect, gunwait; int gunSelect, gunWait;
int lastaction, lastattackgun, lastmove; int lastAction, lastAttackGun, lastMove;
bool attacking; bool attacking;
int ammo[NUMGUNS]; int ammo[NUMGUNS];
int monsterstate; int monsterState;
int mtype; int monsterType;
void *enemy; void *enemy;
float targetyaw; float targetYaw;
bool blocked, moving; bool blocked, moving;
int trigger; int trigger;
OFVector3D attacktarget; OFVector3D attackTarget;
int anger; int anger;
char name[260], team[260]; char name[260], team[260];
}; };
@implementation DynamicEntity @implementation DynamicEntity
+ (instancetype)entity
{
return [[self alloc] init];
}
+ (size_t)serializedSize + (size_t)serializedSize
{ {
return sizeof(struct dynent); return sizeof(struct dynent);
@ -45,6 +50,17 @@ struct dynent {
_ammo = (int *)OFAllocZeroedMemory(NUMGUNS, sizeof(int)); _ammo = (int *)OFAllocZeroedMemory(NUMGUNS, sizeof(int));
_yaw = 270;
_maxSpeed = 22;
_radius = 1.1f;
_eyeHeight = 3.2f;
_aboveEye = 0.7f;
_lastUpdate = lastmillis;
_name = _team = @"";
_state = CS_ALIVE;
[self resetToSpawnState];
return self; return self;
} }
@ -57,54 +73,54 @@ struct dynent {
{ {
DynamicEntity *copy = [[self.class alloc] init]; DynamicEntity *copy = [[self.class alloc] init];
copy->_o = _o; copy->_origin = _origin;
copy->_vel = _vel; copy->_velocity = _velocity;
copy->_yaw = _yaw; copy->_yaw = _yaw;
copy->_pitch = _pitch; copy->_pitch = _pitch;
copy->_roll = _roll; copy->_roll = _roll;
copy->_maxspeed = _maxspeed; copy->_maxSpeed = _maxSpeed;
copy->_outsidemap = _outsidemap; copy->_outsideMap = _outsideMap;
copy->_inwater = _inwater; copy->_inWater = _inWater;
copy->_onfloor = _onfloor; copy->_onFloor = _onFloor;
copy->_jumpnext = _jumpnext; copy->_jumpNext = _jumpNext;
copy->_move = _move; copy->_move = _move;
copy->_strafe = _strafe; copy->_strafe = _strafe;
copy->_k_left = _k_left; copy->_k_left = _k_left;
copy->_k_right = _k_right; copy->_k_right = _k_right;
copy->_k_up = _k_up; copy->_k_up = _k_up;
copy->_k_down = _k_down; copy->_k_down = _k_down;
copy->_timeinair = _timeinair; copy->_timeInAir = _timeInAir;
copy->_radius = _radius; copy->_radius = _radius;
copy->_eyeheight = _eyeheight; copy->_eyeHeight = _eyeHeight;
copy->_aboveeye = _aboveeye; copy->_aboveEye = _aboveEye;
copy->_lastupdate = _lastupdate; copy->_lastUpdate = _lastUpdate;
copy->_plag = _plag; copy->_lag = _lag;
copy->_ping = _ping; copy->_ping = _ping;
copy->_lifesequence = _lifesequence; copy->_lifeSequence = _lifeSequence;
copy->_state = _state; copy->_state = _state;
copy->_frags = _frags; copy->_frags = _frags;
copy->_health = _health; copy->_health = _health;
copy->_armour = _armour; copy->_armour = _armour;
copy->_armourtype = _armourtype; copy->_armourType = _armourType;
copy->_quadmillis = _quadmillis; copy->_quadMillis = _quadMillis;
copy->_gunselect = _gunselect; copy->_gunSelect = _gunSelect;
copy->_gunwait = _gunwait; copy->_gunWait = _gunWait;
copy->_lastaction = _lastaction; copy->_lastAction = _lastAction;
copy->_lastattackgun = _lastattackgun; copy->_lastAttackGun = _lastAttackGun;
copy->_lastmove = _lastmove; copy->_lastMove = _lastMove;
copy->_attacking = _attacking; copy->_attacking = _attacking;
for (size_t i = 0; i < NUMGUNS; i++) for (size_t i = 0; i < NUMGUNS; i++)
copy->_ammo[i] = _ammo[i]; copy->_ammo[i] = _ammo[i];
copy->_monsterstate = _monsterstate; copy->_monsterState = _monsterState;
copy->_mtype = _mtype; copy->_monsterType = _monsterType;
copy->_enemy = _enemy; copy->_enemy = _enemy;
copy->_targetyaw = _targetyaw; copy->_targetYaw = _targetYaw;
copy->_blocked = _blocked; copy->_blocked = _blocked;
copy->_moving = _moving; copy->_moving = _moving;
copy->_trigger = _trigger; copy->_trigger = _trigger;
copy->_attacktarget = _attacktarget; copy->_attackTarget = _attackTarget;
copy->_anger = _anger; copy->_anger = _anger;
copy->_name = [_name copy]; copy->_name = [_name copy];
@ -117,49 +133,49 @@ struct dynent {
{ {
// This is frighteningly *TERRIBLE*, but the format used by existing // This is frighteningly *TERRIBLE*, but the format used by existing
// savegames. // savegames.
struct dynent data = { .o = _o, struct dynent data = { .origin = _origin,
.vel = _vel, .velocity = _velocity,
.yaw = _yaw, .yaw = _yaw,
.pitch = _pitch, .pitch = _pitch,
.roll = _roll, .roll = _roll,
.maxspeed = _maxspeed, .maxSpeed = _maxSpeed,
.outsidemap = _outsidemap, .outsideMap = _outsideMap,
.inwater = _inwater, .inWater = _inWater,
.onfloor = _onfloor, .onFloor = _onFloor,
.jumpnext = _jumpnext, .jumpNext = _jumpNext,
.move = _move, .move = _move,
.strafe = _strafe, .strafe = _strafe,
.k_left = _k_left, .k_left = _k_left,
.k_right = _k_right, .k_right = _k_right,
.k_up = _k_up, .k_up = _k_up,
.k_down = _k_down, .k_down = _k_down,
.timeinair = _timeinair, .timeInAir = _timeInAir,
.radius = _radius, .radius = _radius,
.eyeheight = _eyeheight, .eyeHeight = _eyeHeight,
.aboveeye = _aboveeye, .aboveEye = _aboveEye,
.lastupdate = _lastupdate, .lastUpdate = _lastUpdate,
.plag = _plag, .lag = _lag,
.ping = _ping, .ping = _ping,
.lifesequence = _lifesequence, .lifeSequence = _lifeSequence,
.state = _state, .state = _state,
.frags = _frags, .frags = _frags,
.health = _health, .health = _health,
.armour = _armour, .armour = _armour,
.armourtype = _armourtype, .armourType = _armourType,
.quadmillis = _quadmillis, .quadMillis = _quadMillis,
.gunselect = _gunselect, .gunSelect = _gunSelect,
.gunwait = _gunwait, .gunWait = _gunWait,
.lastaction = _lastaction, .lastAction = _lastAction,
.lastattackgun = _lastattackgun, .lastAttackGun = _lastAttackGun,
.lastmove = _lastmove, .lastMove = _lastMove,
.attacking = _attacking, .attacking = _attacking,
.monsterstate = _monsterstate, .monsterState = _monsterState,
.mtype = _mtype, .monsterType = _monsterType,
.targetyaw = _targetyaw, .targetYaw = _targetYaw,
.blocked = _blocked, .blocked = _blocked,
.moving = _moving, .moving = _moving,
.trigger = _trigger, .trigger = _trigger,
.attacktarget = _attacktarget, .attackTarget = _attackTarget,
.anger = _anger }; .anger = _anger };
for (int i = 0; i < NUMGUNS; i++) for (int i = 0; i < NUMGUNS; i++)
@ -180,56 +196,130 @@ struct dynent {
memcpy(&d, data.items, data.count); memcpy(&d, data.items, data.count);
_o = d.o; _origin = d.origin;
_vel = d.vel; _velocity = d.velocity;
_yaw = d.yaw; _yaw = d.yaw;
_pitch = d.pitch; _pitch = d.pitch;
_roll = d.roll; _roll = d.roll;
_maxspeed = d.maxspeed; _maxSpeed = d.maxSpeed;
_outsidemap = d.outsidemap; _outsideMap = d.outsideMap;
_inwater = d.inwater; _inWater = d.inWater;
_onfloor = d.onfloor; _onFloor = d.onFloor;
_jumpnext = d.jumpnext; _jumpNext = d.jumpNext;
_move = d.move; _move = d.move;
_strafe = d.strafe; _strafe = d.strafe;
_k_left = d.k_left; _k_left = d.k_left;
_k_right = d.k_right; _k_right = d.k_right;
_k_up = d.k_up; _k_up = d.k_up;
_k_down = d.k_down; _k_down = d.k_down;
_timeinair = d.timeinair; _timeInAir = d.timeInAir;
_radius = d.radius; _radius = d.radius;
_eyeheight = d.eyeheight; _eyeHeight = d.eyeHeight;
_aboveeye = d.aboveeye; _aboveEye = d.aboveEye;
_lastupdate = d.lastupdate; _lastUpdate = d.lastUpdate;
_plag = d.plag; _lag = d.lag;
_ping = d.ping; _ping = d.ping;
_lifesequence = d.lifesequence; _lifeSequence = d.lifeSequence;
_state = d.state; _state = d.state;
_frags = d.frags; _frags = d.frags;
_health = d.health; _health = d.health;
_armour = d.armour; _armour = d.armour;
_armourtype = d.armourtype; _armourType = d.armourType;
_quadmillis = d.quadmillis; _quadMillis = d.quadMillis;
_gunselect = d.gunselect; _gunSelect = d.gunSelect;
_gunwait = d.gunwait; _gunWait = d.gunWait;
_lastaction = d.lastaction; _lastAction = d.lastAction;
_lastattackgun = d.lastattackgun; _lastAttackGun = d.lastAttackGun;
_lastmove = d.lastmove; _lastMove = d.lastMove;
_attacking = d.attacking; _attacking = d.attacking;
for (int i = 0; i < NUMGUNS; i++) for (int i = 0; i < NUMGUNS; i++)
_ammo[i] = d.ammo[i]; _ammo[i] = d.ammo[i];
_monsterstate = d.monsterstate; _monsterState = d.monsterState;
_mtype = d.mtype; _monsterType = d.monsterType;
_targetyaw = d.targetyaw; _targetYaw = d.targetYaw;
_blocked = d.blocked; _blocked = d.blocked;
_moving = d.moving; _moving = d.moving;
_trigger = d.trigger; _trigger = d.trigger;
_attacktarget = d.attacktarget; _attackTarget = d.attackTarget;
_anger = d.anger; _anger = d.anger;
_name = [[OFString alloc] initWithUTF8String:d.name]; _name = [[OFString alloc] initWithUTF8String:d.name];
_team = [[OFString alloc] initWithUTF8String:d.team]; _team = [[OFString alloc] initWithUTF8String:d.team];
} }
- (void)resetMovement
{
_k_left = false;
_k_right = false;
_k_up = false;
_k_down = false;
_jumpNext = false;
_strafe = 0;
_move = 0;
}
- (void)resetToSpawnState
{
[self resetMovement];
_velocity = OFMakeVector3D(0, 0, 0);
_onFloor = false;
_timeInAir = 0;
_health = 100;
_armour = 50;
_armourType = A_BLUE;
_quadMillis = 0;
_lastAttackGun = _gunSelect = GUN_SG;
_gunWait = 0;
_attacking = false;
_lastAction = 0;
for (size_t i = 0; i < NUMGUNS; i++)
_ammo[i] = 0;
_ammo[GUN_FIST] = 1;
if (m_noitems) {
_gunSelect = GUN_RIFLE;
_armour = 0;
if (m_noitemsrail) {
_health = 1;
_ammo[GUN_RIFLE] = 100;
} else {
if (gamemode == 12) {
// eihrul's secret "instafist" mode
_gunSelect = GUN_FIST;
return;
}
_health = 256;
if (m_tarena) {
_gunSelect = rnd(4) + 1;
baseammo(_gunSelect);
int gun2;
do {
gun2 = rnd(4) + 1;
} while (gun2 != _gunSelect);
baseammo(gun2);
} else if (m_arena) {
// insta arena
_ammo[GUN_RIFLE] = 100;
} else {
// efficiency
for (size_t i = 0; i < 4; i++)
baseammo(i + 1);
_gunSelect = GUN_CG;
}
_ammo[GUN_CG] /= 2;
}
} else
_ammo[GUN_SG] = 5;
}
@end @end

View file

@ -21,7 +21,7 @@ renderclient(
{ {
int n = 3; int n = 3;
float speed = 100.0f; float speed = 100.0f;
float mz = d.o.z - d.eyeheight + 1.55f * scale; float mz = d.origin.z - d.eyeHeight + 1.55f * scale;
intptr_t tmp = (intptr_t)d; intptr_t tmp = (intptr_t)d;
int basetime = -(tmp & 0xFFF); int basetime = -(tmp & 0xFFF);
if (d.state == CS_DEAD) { if (d.state == CS_DEAD) {
@ -33,8 +33,8 @@ renderclient(
n = (intptr_t)d % 3; n = (intptr_t)d % 3;
r = range[n]; r = range[n];
} }
basetime = d.lastaction; basetime = d.lastAction;
int t = lastmillis - d.lastaction; int t = lastmillis - d.lastAction;
if (t < 0 || t > 20000) if (t < 0 || t > 20000)
return; return;
if (t > (r - 1) * 100) { if (t > (r - 1) * 100) {
@ -47,25 +47,25 @@ renderclient(
if (mz < -1000) if (mz < -1000)
return; return;
// mdl = (((int)d>>6)&1)+1; // mdl = (((int)d>>6)&1)+1;
// mz = d.o.z-d.eyeheight+0.2f; // mz = d.o.z-d.eyeHeight+0.2f;
// scale = 1.2f; // scale = 1.2f;
} else if (d.state == CS_EDITING) { } else if (d.state == CS_EDITING) {
n = 16; n = 16;
} else if (d.state == CS_LAGGED) { } else if (d.state == CS_LAGGED) {
n = 17; n = 17;
} else if (d.monsterstate == M_ATTACKING) { } else if (d.monsterState == M_ATTACKING) {
n = 8; n = 8;
} else if (d.monsterstate == M_PAIN) { } else if (d.monsterState == M_PAIN) {
n = 10; n = 10;
} else if ((!d.move && !d.strafe) || !d.moving) { } else if ((!d.move && !d.strafe) || !d.moving) {
n = 12; n = 12;
} else if (!d.onfloor && d.timeinair > 100) { } else if (!d.onFloor && d.timeInAir > 100) {
n = 18; n = 18;
} else { } else {
n = 14; n = 14;
speed = 1200 / d.maxspeed * scale; speed = 1200 / d.maxSpeed * scale;
if (hellpig) if (hellpig)
speed = 300 / d.maxspeed; speed = 300 / d.maxSpeed;
} }
if (hellpig) { if (hellpig) {
n++; n++;
@ -73,8 +73,8 @@ renderclient(
mz -= 1.9f; mz -= 1.9f;
} }
rendermodel(mdlname, frame[n], range[n], 0, 1.5f, rendermodel(mdlname, frame[n], range[n], 0, 1.5f,
OFMakeVector3D(d.o.x, mz, d.o.y), d.yaw + 90, d.pitch / 2, team, OFMakeVector3D(d.origin.x, mz, d.origin.y), d.yaw + 90, d.pitch / 2,
scale, speed, 0, basetime); team, scale, speed, 0, basetime);
} }
extern int democlientnum; extern int democlientnum;
@ -107,7 +107,7 @@ static OFMutableArray<OFString *> *scoreLines;
void void
renderscore(DynamicEntity *d) renderscore(DynamicEntity *d)
{ {
OFString *lag = [OFString stringWithFormat:@"%d", d.plag]; OFString *lag = [OFString stringWithFormat:@"%d", d.lag];
OFString *name = [OFString stringWithFormat:@"(%@)", d.name]; OFString *name = [OFString stringWithFormat:@"(%@)", d.name];
OFString *line = OFString *line =
[OFString stringWithFormat:@"%d\t%@\t%d\t%@\t%@", d.frags, [OFString stringWithFormat:@"%d\t%@\t%d\t%@\t%@", d.frags,

View file

@ -24,7 +24,7 @@ OFMutableArray *players; // other clients
void void
initPlayers() initPlayers()
{ {
player1 = newdynent(); player1 = [[DynamicEntity alloc] init];
players = [[OFMutableArray alloc] init]; players = [[OFMutableArray alloc] init];
} }
@ -42,101 +42,6 @@ getclientmap()
return clientmap; return clientmap;
} }
void
resetmovement(DynamicEntity *d)
{
d.k_left = false;
d.k_right = false;
d.k_up = false;
d.k_down = false;
d.jumpnext = false;
d.strafe = 0;
d.move = 0;
}
// reset player state not persistent accross spawns
void
spawnstate(DynamicEntity *d)
{
resetmovement(d);
d.vel = OFMakeVector3D(0, 0, 0);
d.onfloor = false;
d.timeinair = 0;
d.health = 100;
d.armour = 50;
d.armourtype = A_BLUE;
d.quadmillis = 0;
d.lastattackgun = d.gunselect = GUN_SG;
d.gunwait = 0;
d.attacking = false;
d.lastaction = 0;
loopi(NUMGUNS) d.ammo[i] = 0;
d.ammo[GUN_FIST] = 1;
if (m_noitems) {
d.gunselect = GUN_RIFLE;
d.armour = 0;
if (m_noitemsrail) {
d.health = 1;
d.ammo[GUN_RIFLE] = 100;
} else {
if (gamemode == 12) {
// eihrul's secret "instafist" mode
d.gunselect = GUN_FIST;
return;
}
d.health = 256;
if (m_tarena) {
int gun1 = rnd(4) + 1;
baseammo(d.gunselect = gun1);
for (;;) {
int gun2 = rnd(4) + 1;
if (gun1 != gun2) {
baseammo(gun2);
break;
}
}
} else if (m_arena) {
// insta arena
d.ammo[GUN_RIFLE] = 100;
} else {
// efficiency
loopi(4) baseammo(i + 1);
d.gunselect = GUN_CG;
}
d.ammo[GUN_CG] /= 2;
}
} else
d.ammo[GUN_SG] = 5;
}
DynamicEntity *
newdynent() // create a new blank player or monster
{
DynamicEntity *d = [[DynamicEntity alloc] init];
d.o = OFMakeVector3D(0, 0, 0);
d.yaw = 270;
d.pitch = 0;
d.roll = 0;
d.maxspeed = 22;
d.outsidemap = false;
d.inwater = false;
d.radius = 1.1f;
d.eyeheight = 3.2f;
d.aboveeye = 0.7f;
d.frags = 0;
d.plag = 0;
d.ping = 0;
d.lastupdate = lastmillis;
d.enemy = NULL;
d.monsterstate = 0;
d.name = d.team = @"";
d.blocked = false;
d.lifesequence = 0;
d.state = CS_ALIVE;
spawnstate(d);
return d;
}
void void
respawnself() respawnself()
{ {
@ -203,7 +108,7 @@ otherplayers()
if (player == [OFNull null]) if (player == [OFNull null])
return; return;
const int lagtime = lastmillis - [player lastupdate]; const int lagtime = lastmillis - [player lastUpdate];
if (lagtime > 1000 && [player state] == CS_ALIVE) { if (lagtime > 1000 && [player state] == CS_ALIVE) {
[player setState:CS_LAGGED]; [player setState:CS_LAGGED];
return; return;
@ -271,11 +176,11 @@ updateworld(int millis) // main game update loop
if (!demoplayback) { if (!demoplayback) {
monsterthink(); monsterthink();
if (player1.state == CS_DEAD) { if (player1.state == CS_DEAD) {
if (lastmillis - player1.lastaction < 2000) { if (lastmillis - player1.lastAction < 2000) {
player1.move = player1.strafe = 0; player1.move = player1.strafe = 0;
moveplayer(player1, 10, false); moveplayer(player1, 10, false);
} else if (!m_arena && !m_sp && } else if (!m_arena && !m_sp &&
lastmillis - player1.lastaction > 10000) lastmillis - player1.lastAction > 10000)
respawn(); respawn();
} else if (!intermission) { } else if (!intermission) {
moveplayer(player1, 20, true); moveplayer(player1, 20, true);
@ -296,14 +201,14 @@ entinmap(DynamicEntity *d)
{ {
float dx = (rnd(21) - 10) / 10.0f * i; // increasing distance float dx = (rnd(21) - 10) / 10.0f * i; // increasing distance
float dy = (rnd(21) - 10) / 10.0f * i; float dy = (rnd(21) - 10) / 10.0f * i;
OFVector3D old = d.o; OFVector3D old = d.origin;
d.o = OFMakeVector3D(d.o.x + dx, d.o.y + dy, d.o.z); d.origin = OFAddVector3D(d.origin, OFMakeVector3D(dx, dy, 0));
if (collide(d, true, 0, 0)) if (collide(d, true, 0, 0))
return; return;
d.o = old; d.origin = old;
} }
conoutf( conoutf(@"can't find entity spawn spot! (%d, %d)", (int)d.origin.x,
@"can't find entity spawn spot! (%d, %d)", (int)d.o.x, (int)d.o.y); (int)d.origin.y);
// leave ent at original pos, possibly stuck // leave ent at original pos, possibly stuck
} }
@ -317,15 +222,16 @@ spawnplayer(DynamicEntity *d)
int r = fixspawn-- > 0 ? 4 : rnd(10) + 1; int r = fixspawn-- > 0 ? 4 : rnd(10) + 1;
loopi(r) spawncycle = findentity(PLAYERSTART, spawncycle + 1); loopi(r) spawncycle = findentity(PLAYERSTART, spawncycle + 1);
if (spawncycle != -1) { if (spawncycle != -1) {
d.o = OFMakeVector3D( d.origin = OFMakeVector3D(
ents[spawncycle].x, ents[spawncycle].y, ents[spawncycle].z); ents[spawncycle].x, ents[spawncycle].y, ents[spawncycle].z);
d.yaw = ents[spawncycle].attr1; d.yaw = ents[spawncycle].attr1;
d.pitch = 0; d.pitch = 0;
d.roll = 0; d.roll = 0;
} else } else
d.o = OFMakeVector3D((float)ssize / 2, (float)ssize / 2, 4); d.origin =
OFMakeVector3D((float)ssize / 2, (float)ssize / 2, 4);
entinmap(d); entinmap(d);
spawnstate(d); [d resetToSpawnState];
d.state = CS_ALIVE; d.state = CS_ALIVE;
} }
@ -336,7 +242,7 @@ spawnplayer(DynamicEntity *d)
{ \ { \
player1.s = isdown; \ player1.s = isdown; \
player1.v = isdown ? d : (player1.os ? -(d) : 0); \ player1.v = isdown ? d : (player1.os ? -(d) : 0); \
player1.lastmove = lastmillis; \ player1.lastMove = lastmillis; \
} }
dir(backward, move, -1, k_down, k_up); dir(backward, move, -1, k_down, k_up);
@ -358,7 +264,7 @@ attack(bool on)
void void
jumpn(bool on) jumpn(bool on)
{ {
if (!intermission && (player1.jumpnext = on)) if (!intermission && (player1.jumpNext = on))
respawn(); respawn();
} }
@ -406,7 +312,7 @@ selfdamage(int damage, int actor, DynamicEntity *act)
damageblend(damage); damageblend(damage);
demoblend(damage); demoblend(damage);
// let armour absorb when possible // let armour absorb when possible
int ad = damage * (player1.armourtype + 1) * 20 / 100; int ad = damage * (player1.armourType + 1) * 20 / 100;
if (ad > player1.armour) if (ad > player1.armour)
ad = player1.armour; ad = player1.armour;
player1.armour -= ad; player1.armour -= ad;
@ -440,14 +346,14 @@ selfdamage(int damage, int actor, DynamicEntity *act)
} }
showscores(true); showscores(true);
addmsg(1, 2, SV_DIED, actor); addmsg(1, 2, SV_DIED, actor);
player1.lifesequence++; player1.lifeSequence++;
player1.attacking = false; player1.attacking = false;
player1.state = CS_DEAD; player1.state = CS_DEAD;
player1.pitch = 0; player1.pitch = 0;
player1.roll = 60; player1.roll = 60;
playsound(S_DIE1 + rnd(2), NULL); playsound(S_DIE1 + rnd(2), NULL);
spawnstate(player1); [player1 resetToSpawnState];
player1.lastaction = lastmillis; player1.lastAction = lastmillis;
} else } else
playsound(S_PAIN6, NULL); playsound(S_PAIN6, NULL);
} }
@ -473,10 +379,17 @@ getclient(int cn) // ensure valid entity
neterr(@"clientnum"); neterr(@"clientnum");
return nil; return nil;
} }
while (cn >= players.count) while (cn >= players.count)
[players addObject:[OFNull null]]; [players addObject:[OFNull null]];
return (players[cn] != [OFNull null] ? players[cn]
: (players[cn] = newdynent())); id player = players[cn];
if (player == [OFNull null]) {
player = [DynamicEntity entity];
players[cn] = player;
}
return player;
} }
void void

View file

@ -142,7 +142,7 @@ disconnect(bool onlyclean, bool async)
disconnecting = 0; disconnecting = 0;
clientnum = -1; clientnum = -1;
c2sinit = false; c2sinit = false;
player1.lifesequence = 0; player1.lifeSequence = 0;
[players removeAllObjects]; [players removeAllObjects];
localdisconnect(); localdisconnect();
@ -300,20 +300,20 @@ c2sinfo(DynamicEntity *d)
putint(&p, clientnum); putint(&p, clientnum);
// quantize coordinates to 1/16th of a cube, between 1 and 3 // quantize coordinates to 1/16th of a cube, between 1 and 3
// bytes // bytes
putint(&p, (int)(d.o.x * DMF)); putint(&p, (int)(d.origin.x * DMF));
putint(&p, (int)(d.o.y * DMF)); putint(&p, (int)(d.origin.y * DMF));
putint(&p, (int)(d.o.z * DMF)); putint(&p, (int)(d.origin.z * DMF));
putint(&p, (int)(d.yaw * DAF)); putint(&p, (int)(d.yaw * DAF));
putint(&p, (int)(d.pitch * DAF)); putint(&p, (int)(d.pitch * DAF));
putint(&p, (int)(d.roll * DAF)); putint(&p, (int)(d.roll * DAF));
// quantize to 1/100, almost always 1 byte // quantize to 1/100, almost always 1 byte
putint(&p, (int)(d.vel.x * DVF)); putint(&p, (int)(d.velocity.x * DVF));
putint(&p, (int)(d.vel.y * DVF)); putint(&p, (int)(d.velocity.y * DVF));
putint(&p, (int)(d.vel.z * DVF)); putint(&p, (int)(d.velocity.z * DVF));
// pack rest in 1 byte: strafe:2, move:2, onfloor:1, state:3 // pack rest in 1 byte: strafe:2, move:2, onFloor:1, state:3
putint(&p, putint(&p,
(d.strafe & 3) | ((d.move & 3) << 2) | (d.strafe & 3) | ((d.move & 3) << 2) |
(((int)d.onfloor) << 4) | (((int)d.onFloor) << 4) |
((editmode ? CS_EDITING : d.state) << 5)); ((editmode ? CS_EDITING : d.state) << 5));
if (senditemstoserver) { if (senditemstoserver) {
@ -339,7 +339,7 @@ c2sinfo(DynamicEntity *d)
putint(&p, SV_INITC2S); putint(&p, SV_INITC2S);
sendstring(player1.name, &p); sendstring(player1.name, &p);
sendstring(player1.team, &p); sendstring(player1.team, &p);
putint(&p, player1.lifesequence); putint(&p, player1.lifeSequence);
} }
for (OFData *msg in messages) { for (OFData *msg in messages) {
// send messages collected during the previous frames // send messages collected during the previous frames

View file

@ -38,26 +38,27 @@ void
updatepos(DynamicEntity *d) updatepos(DynamicEntity *d)
{ {
const float r = player1.radius + d.radius; const float r = player1.radius + d.radius;
const float dx = player1.o.x - d.o.x; const float dx = player1.origin.x - d.origin.x;
const float dy = player1.o.y - d.o.y; const float dy = player1.origin.y - d.origin.y;
const float dz = player1.o.z - d.o.z; const float dz = player1.origin.z - d.origin.z;
const float rz = player1.aboveeye + d.eyeheight; const float rz = player1.aboveEye + d.eyeHeight;
const float fx = (float)fabs(dx), fy = (float)fabs(dy), const float fx = (float)fabs(dx), fy = (float)fabs(dy),
fz = (float)fabs(dz); fz = (float)fabs(dz);
if (fx < r && fy < r && fz < rz && d.state != CS_DEAD) { if (fx < r && fy < r && fz < rz && d.state != CS_DEAD) {
if (fx < fy) if (fx < fy)
// push aside // push aside
d.o = OFMakeVector3D(d.o.x, d.origin = OFAddVector3D(d.origin,
d.o.y + (dy < 0 ? r - fy : -(r - fy)), d.o.z); OFMakeVector3D(
0, (dy < 0 ? r - fy : -(r - fy)), 0));
else else
d.o = OFMakeVector3D( d.origin = OFAddVector3D(d.origin,
d.o.x + (dx < 0 ? r - fx : -(r - fx)), d.o.y, OFMakeVector3D(
d.o.z); (dx < 0 ? r - fx : -(r - fx)), 0, 0));
} }
int lagtime = lastmillis - d.lastupdate; int lagtime = lastmillis - d.lastUpdate;
if (lagtime) { if (lagtime) {
d.plag = (d.plag * 5 + lagtime) / 6; d.lag = (d.lag * 5 + lagtime) / 6;
d.lastupdate = lastmillis; d.lastUpdate = lastmillis;
} }
} }
@ -118,22 +119,22 @@ localservertoclient(uchar *buf, int len)
tmp.x = getint(&p) / DMF; tmp.x = getint(&p) / DMF;
tmp.y = getint(&p) / DMF; tmp.y = getint(&p) / DMF;
tmp.z = getint(&p) / DMF; tmp.z = getint(&p) / DMF;
d.o = tmp; d.origin = tmp;
d.yaw = getint(&p) / DAF; d.yaw = getint(&p) / DAF;
d.pitch = getint(&p) / DAF; d.pitch = getint(&p) / DAF;
d.roll = getint(&p) / DAF; d.roll = getint(&p) / DAF;
tmp.x = getint(&p) / DVF; tmp.x = getint(&p) / DVF;
tmp.y = getint(&p) / DVF; tmp.y = getint(&p) / DVF;
tmp.z = getint(&p) / DVF; tmp.z = getint(&p) / DVF;
d.vel = tmp; d.velocity = tmp;
int f = getint(&p); int f = getint(&p);
d.strafe = (f & 3) == 3 ? -1 : f & 3; d.strafe = (f & 3) == 3 ? -1 : f & 3;
f >>= 2; f >>= 2;
d.move = (f & 3) == 3 ? -1 : f & 3; d.move = (f & 3) == 3 ? -1 : f & 3;
d.onfloor = (f >> 2) & 1; d.onFloor = (f >> 2) & 1;
int state = f >> 3; int state = f >> 3;
if (state == CS_DEAD && d.state != CS_DEAD) if (state == CS_DEAD && d.state != CS_DEAD)
d.lastaction = lastmillis; d.lastAction = lastmillis;
d.state = state; d.state = state;
if (!demoplayback) if (!demoplayback)
updatepos(d); updatepos(d);
@ -141,7 +142,7 @@ localservertoclient(uchar *buf, int len)
} }
case SV_SOUND: { case SV_SOUND: {
OFVector3D loc = d.o; OFVector3D loc = d.origin;
playsound(getint(&p), &loc); playsound(getint(&p), &loc);
break; break;
} }
@ -197,7 +198,7 @@ localservertoclient(uchar *buf, int len)
d.name = @(text); d.name = @(text);
sgetstr(); sgetstr();
d.team = @(text); d.team = @(text);
d.lifesequence = getint(&p); d.lifeSequence = getint(&p);
break; break;
} }
@ -230,10 +231,10 @@ localservertoclient(uchar *buf, int len)
int damage = getint(&p); int damage = getint(&p);
int ls = getint(&p); int ls = getint(&p);
if (target == clientnum) { if (target == clientnum) {
if (ls == player1.lifesequence) if (ls == player1.lifeSequence)
selfdamage(damage, cn, d); selfdamage(damage, cn, d);
} else { } else {
OFVector3D loc = getclient(target).o; OFVector3D loc = getclient(target).origin;
playsound(S_PAIN1 + rnd(5), &loc); playsound(S_PAIN1 + rnd(5), &loc);
} }
break; break;
@ -267,9 +268,9 @@ localservertoclient(uchar *buf, int len)
a.name, d.name); a.name, d.name);
} }
} }
OFVector3D loc = d.o; OFVector3D loc = d.origin;
playsound(S_DIE1 + rnd(2), &loc); playsound(S_DIE1 + rnd(2), &loc);
d.lifesequence++; d.lifeSequence++;
break; break;
} }

View file

@ -281,32 +281,10 @@ extern bool demoplayback;
// simplistic vector ops // simplistic vector ops
#define dotprod(u, v) ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z) #define dotprod(u, v) ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z)
#define vmul(u, f) \ #define vmul(u, f) u = OFMultiplyVector3D(u, OFMakeVector3D(f, f, f))
{ \ #define vdiv(u, f) u = OFDivideVector3D(u, OFMakeVector3D(f, f, f))
OFVector3D tmp_ = u; \ #define vadd(u, v) u = OFAddVector3D(u, v)
float tmp2_ = f; \ #define vsub(u, v) u = OFSubtractVector3D(u, v)
u = OFMakeVector3D( \
tmp_.x * tmp2_, tmp_.y * tmp2_, tmp_.z * tmp2_); \
}
#define vdiv(u, f) \
{ \
OFVector3D tmp_ = u; \
float tmp2_ = f; \
u = OFMakeVector3D( \
tmp_.x / tmp2_, tmp_.y / tmp2_, tmp_.z / tmp2_); \
}
#define vadd(u, v) \
{ \
OFVector3D tmp_ = u; \
u = OFMakeVector3D( \
tmp_.x + (v).x, tmp_.y + (v).y, tmp_.z + (v).z); \
}
#define vsub(u, v) \
{ \
OFVector3D tmp_ = u; \
u = OFMakeVector3D( \
tmp_.x - (v).x, tmp_.y - (v).y, tmp_.z - (v).z); \
}
#define vdist(d, v, e, s) \ #define vdist(d, v, e, s) \
OFVector3D v = s; \ OFVector3D v = s; \
vsub(v, e); \ vsub(v, e); \

View file

@ -169,8 +169,9 @@ cursorupdate() // called every frame from hud
// selected wall // selected wall
if (fabs(sheight(s, s, z) - z) > 1) { if (fabs(sheight(s, s, z) - z) > 1) {
x += x > player1.o.x ? 0.5f : -0.5f; // find right wall cube // find right wall cube
y += y > player1.o.y ? 0.5f : -0.5f; x += (x > player1.origin.x ? 0.5f : -0.5f);
y += (y > player1.origin.y ? 0.5f : -0.5f);
cx = (int)x; cx = (int)x;
cy = (int)y; cy = (int)y;
@ -622,7 +623,7 @@ void
newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4) newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4)
{ {
EDITSEL; EDITSEL;
newentity(sel.x, sel.y, (int)player1.o.z, what, newentity(sel.x, sel.y, (int)player1.origin.z, what,
[a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0], [a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0],
[a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]); [a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]);
} }

View file

@ -171,16 +171,16 @@ realpickup(int n, DynamicEntity *d)
case I_GREENARMOUR: case I_GREENARMOUR:
d.armour = radditem(n, d.armour); d.armour = radditem(n, d.armour);
d.armourtype = A_GREEN; d.armourType = A_GREEN;
break; break;
case I_YELLOWARMOUR: case I_YELLOWARMOUR:
d.armour = radditem(n, d.armour); d.armour = radditem(n, d.armour);
d.armourtype = A_YELLOW; d.armourType = A_YELLOW;
break; break;
case I_QUAD: case I_QUAD:
d.quadmillis = radditem(n, d.quadmillis); d.quadMillis = radditem(n, d.quadMillis);
conoutf(@"you got the quad!"); conoutf(@"you got the quad!");
break; break;
} }
@ -214,10 +214,11 @@ teleport(int n, DynamicEntity *d)
if (beenhere < 0) if (beenhere < 0)
beenhere = e; beenhere = e;
if (ents[e].attr2 == tag) { if (ents[e].attr2 == tag) {
d.o = OFMakeVector3D(ents[e].x, ents[e].y, ents[e].z); d.origin =
OFMakeVector3D(ents[e].x, ents[e].y, ents[e].z);
d.yaw = ents[e].attr1; d.yaw = ents[e].attr1;
d.pitch = 0; d.pitch = 0;
d.vel = OFMakeVector3D(0, 0, 0); d.velocity = OFMakeVector3D(0, 0, 0);
entinmap(d); entinmap(d);
playsoundc(S_TELEPORT); playsoundc(S_TELEPORT);
break; break;
@ -257,7 +258,7 @@ pickup(int n, DynamicEntity *d)
case I_GREENARMOUR: case I_GREENARMOUR:
// (100h/100g only absorbs 166 damage) // (100h/100g only absorbs 166 damage)
if (d.armourtype == A_YELLOW && d.armour > 66) if (d.armourType == A_YELLOW && d.armour > 66)
break; break;
additem(n, d.armour, 20); additem(n, d.armour, 20);
break; break;
@ -267,7 +268,7 @@ pickup(int n, DynamicEntity *d)
break; break;
case I_QUAD: case I_QUAD:
additem(n, d.quadmillis, 60); additem(n, d.quadMillis, 60);
break; break;
case CARROT: case CARROT:
@ -293,8 +294,9 @@ pickup(int n, DynamicEntity *d)
lastjumppad = lastmillis; lastjumppad = lastmillis;
OFVector3D v = OFMakeVector3D((int)(char)ents[n].attr3 / 10.0f, OFVector3D v = OFMakeVector3D((int)(char)ents[n].attr3 / 10.0f,
(int)(char)ents[n].attr2 / 10.0f, ents[n].attr1 / 10.0f); (int)(char)ents[n].attr2 / 10.0f, ents[n].attr1 / 10.0f);
player1.vel = OFMakeVector3D(player1.vel.x, player1.vel.y, 0); player1.velocity =
vadd(player1.vel, v); OFMakeVector3D(player1.velocity.x, player1.velocity.y, 0);
vadd(player1.velocity, v);
playsoundc(S_JUMPPAD); playsoundc(S_JUMPPAD);
break; break;
} }
@ -318,8 +320,8 @@ checkitems()
return; return;
OFVector3D v = OFMakeVector3D( OFVector3D v = OFMakeVector3D(
e.x, e.y, (float)S(e.x, e.y)->floor + player1.eyeheight); e.x, e.y, (float)S(e.x, e.y)->floor + player1.eyeHeight);
vdist(dist, t, player1.o, v); vdist(dist, t, player1.origin, v);
if (dist < (e.type == TELEPORT ? 4 : 2.5)) if (dist < (e.type == TELEPORT ? 4 : 2.5))
pickup(i, player1); pickup(i, player1);
@ -329,8 +331,8 @@ checkitems()
void void
checkquad(int time) checkquad(int time)
{ {
if (player1.quadmillis && (player1.quadmillis -= time) < 0) { if (player1.quadMillis && (player1.quadMillis -= time) < 0) {
player1.quadmillis = 0; player1.quadMillis = 0;
playsoundc(S_PUPOUT); playsoundc(S_PUPOUT);
conoutf(@"quad damage is over"); conoutf(@"quad damage is over");
} }

View file

@ -3,6 +3,8 @@
#include "cube.h" #include "cube.h"
#import "Menu.h" #import "Menu.h"
#import "DynamicEntity.h"
#import "MenuItem.h" #import "MenuItem.h"
static OFMutableArray<OFNumber *> *menuStack; static OFMutableArray<OFNumber *> *menuStack;
@ -13,7 +15,7 @@ void
menuset(int menu) menuset(int menu)
{ {
if ((vmenu = menu) >= 1) if ((vmenu = menu) >= 1)
resetmovement(player1); [player1 resetMovement];
if (vmenu == 1) if (vmenu == 1)
menus[1].menusel = 0; menus[1].menusel = 0;
} }

View file

@ -62,22 +62,22 @@ basicmonster(int type, int yaw, int state, int trigger, int move)
conoutf(@"warning: unknown monster in spawn: %d", type); conoutf(@"warning: unknown monster in spawn: %d", type);
type = 0; type = 0;
} }
DynamicEntity *m = newdynent(); DynamicEntity *m = [DynamicEntity entity];
struct monstertype *t = &monstertypes[(m.mtype = type)]; struct monstertype *t = &monstertypes[(m.monsterType = type)];
m.eyeheight = 2.0f; m.eyeHeight = 2.0f;
m.aboveeye = 1.9f; m.aboveEye = 1.9f;
m.radius *= t->bscale / 10.0f; m.radius *= t->bscale / 10.0f;
m.eyeheight *= t->bscale / 10.0f; m.eyeHeight *= t->bscale / 10.0f;
m.aboveeye *= t->bscale / 10.0f; m.aboveEye *= t->bscale / 10.0f;
m.monsterstate = state; m.monsterState = state;
if (state != M_SLEEP) if (state != M_SLEEP)
spawnplayer(m); spawnplayer(m);
m.trigger = lastmillis + trigger; m.trigger = lastmillis + trigger;
m.targetyaw = m.yaw = (float)yaw; m.targetYaw = m.yaw = (float)yaw;
m.move = move; m.move = move;
m.enemy = player1; m.enemy = player1;
m.gunselect = t->gun; m.gunSelect = t->gun;
m.maxspeed = (float)t->speed; m.maxSpeed = (float)t->speed;
m.health = t->health; m.health = t->health;
m.armour = 0; m.armour = 0;
loopi(NUMGUNS) m.ammo[i] = 10000; loopi(NUMGUNS) m.ammo[i] = 10000;
@ -129,7 +129,7 @@ monsterclear()
DynamicEntity *m = DynamicEntity *m =
basicmonster(e.attr2, e.attr1, M_SLEEP, 100, 0); basicmonster(e.attr2, e.attr1, M_SLEEP, 100, 0);
m.o = OFMakeVector3D(e.x, e.y, e.z); m.origin = OFMakeVector3D(e.x, e.y, e.z);
entinmap(m); entinmap(m);
monstertotal++; monstertotal++;
} }
@ -176,9 +176,9 @@ los(float lx, float ly, float lz, float bx, float by, float bz, OFVector3D *v)
bool bool
enemylos(DynamicEntity *m, OFVector3D *v) enemylos(DynamicEntity *m, OFVector3D *v)
{ {
*v = m.o; *v = m.origin;
return los( return los(m.origin.x, m.origin.y, m.origin.z, m.enemy.origin.x,
m.o.x, m.o.y, m.o.z, m.enemy.o.x, m.enemy.o.y, m.enemy.o.z, v); m.enemy.origin.y, m.enemy.origin.z, v);
} }
// monster AI is sequenced using transitions: they are in a particular state // monster AI is sequenced using transitions: they are in a particular state
@ -192,7 +192,7 @@ enemylos(DynamicEntity *m, OFVector3D *v)
void void
transition(DynamicEntity *m, int state, int moving, int n, int r) transition(DynamicEntity *m, int state, int moving, int n, int r)
{ {
m.monsterstate = state; m.monsterState = state;
m.move = moving; m.move = moving;
n = n * 130 / 100; n = n * 130 / 100;
m.trigger = lastmillis + n - skill * (n / 16) + rnd(r + 1); m.trigger = lastmillis + n - skill * (n / 16) + rnd(r + 1);
@ -215,41 +215,42 @@ monsteraction(DynamicEntity *m)
m.enemy = player1; m.enemy = player1;
m.anger = 0; m.anger = 0;
} }
normalise(m, m.targetyaw); normalise(m, m.targetYaw);
// slowly turn monster towards his target // slowly turn monster towards his target
if (m.targetyaw > m.yaw) { if (m.targetYaw > m.yaw) {
m.yaw += curtime * 0.5f; m.yaw += curtime * 0.5f;
if (m.targetyaw < m.yaw) if (m.targetYaw < m.yaw)
m.yaw = m.targetyaw; m.yaw = m.targetYaw;
} else { } else {
m.yaw -= curtime * 0.5f; m.yaw -= curtime * 0.5f;
if (m.targetyaw > m.yaw) if (m.targetYaw > m.yaw)
m.yaw = m.targetyaw; m.yaw = m.targetYaw;
} }
vdist(disttoenemy, vectoenemy, m.o, m.enemy.o); vdist(disttoenemy, vectoenemy, m.origin, m.enemy.origin);
m.pitch = atan2(m.enemy.o.z - m.o.z, disttoenemy) * 180 / PI; m.pitch = atan2(m.enemy.origin.z - m.origin.z, disttoenemy) * 180 / PI;
// special case: if we run into scenery // special case: if we run into scenery
if (m.blocked) { if (m.blocked) {
m.blocked = false; m.blocked = false;
// try to jump over obstackle (rare) // try to jump over obstackle (rare)
if (!rnd(20000 / monstertypes[m.mtype].speed)) if (!rnd(20000 / monstertypes[m.monsterType].speed))
m.jumpnext = true; m.jumpNext = true;
// search for a way around (common) // search for a way around (common)
else if (m.trigger < lastmillis && else if (m.trigger < lastmillis &&
(m.monsterstate != M_HOME || !rnd(5))) { (m.monsterState != M_HOME || !rnd(5))) {
// patented "random walk" AI pathfinding (tm) ;) // patented "random walk" AI pathfinding (tm) ;)
m.targetyaw += 180 + rnd(180); m.targetYaw += 180 + rnd(180);
transition(m, M_SEARCH, 1, 400, 1000); transition(m, M_SEARCH, 1, 400, 1000);
} }
} }
float enemyyaw = float enemyYaw = -(float)atan2(m.enemy.origin.x - m.origin.x,
-(float)atan2(m.enemy.o.x - m.o.x, m.enemy.o.y - m.o.y) / PI * 180 + m.enemy.origin.y - m.origin.y) /
PI * 180 +
180; 180;
switch (m.monsterstate) { switch (m.monsterState) {
case M_PAIN: case M_PAIN:
case M_ATTACKING: case M_ATTACKING:
case M_SEARCH: case M_SEARCH:
@ -263,15 +264,15 @@ monsteraction(DynamicEntity *m)
OFVector3D target; OFVector3D target;
if (editmode || !enemylos(m, &target)) if (editmode || !enemylos(m, &target))
return; // skip running physics return; // skip running physics
normalise(m, enemyyaw); normalise(m, enemyYaw);
float angle = (float)fabs(enemyyaw - m.yaw); float angle = (float)fabs(enemyYaw - m.yaw);
if (disttoenemy < 8 // the better the angle to the player, the if (disttoenemy < 8 // the better the angle to the player, the
// further the monster can see/hear // further the monster can see/hear
|| (disttoenemy < 16 && angle < 135) || || (disttoenemy < 16 && angle < 135) ||
(disttoenemy < 32 && angle < 90) || (disttoenemy < 32 && angle < 90) ||
(disttoenemy < 64 && angle < 45) || angle < 10) { (disttoenemy < 64 && angle < 45) || angle < 10) {
transition(m, M_HOME, 1, 500, 200); transition(m, M_HOME, 1, 500, 200);
OFVector3D loc = m.o; OFVector3D loc = m.origin;
playsound(S_GRUNT1 + rnd(2), &loc); playsound(S_GRUNT1 + rnd(2), &loc);
} }
break; break;
@ -281,10 +282,10 @@ monsteraction(DynamicEntity *m)
// this state is the delay between wanting to shoot and actually // this state is the delay between wanting to shoot and actually
// firing // firing
if (m.trigger < lastmillis) { if (m.trigger < lastmillis) {
m.lastaction = 0; m.lastAction = 0;
m.attacking = true; m.attacking = true;
OFVector3D attacktarget = m.attacktarget; OFVector3D attackTarget = m.attackTarget;
shoot(m, &attacktarget); shoot(m, &attackTarget);
transition(m, M_ATTACKING, 0, 600, 0); transition(m, M_ATTACKING, 0, 600, 0);
} }
break; break;
@ -292,7 +293,7 @@ monsteraction(DynamicEntity *m)
case M_HOME: case M_HOME:
// monster has visual contact, heads straight for player and // monster has visual contact, heads straight for player and
// may want to shoot at any time // may want to shoot at any time
m.targetyaw = enemyyaw; m.targetYaw = enemyYaw;
if (m.trigger < lastmillis) { if (m.trigger < lastmillis) {
OFVector3D target; OFVector3D target;
if (!enemylos(m, &target)) { if (!enemylos(m, &target)) {
@ -305,13 +306,15 @@ monsteraction(DynamicEntity *m)
if (!rnd((int)disttoenemy / 3 + 1) && if (!rnd((int)disttoenemy / 3 + 1) &&
m.enemy.state == CS_ALIVE) { m.enemy.state == CS_ALIVE) {
// get ready to fire // get ready to fire
m.attacktarget = target; m.attackTarget = target;
transition(m, M_AIMING, 0, transition(m, M_AIMING, 0,
monstertypes[m.mtype].lag, 10); monstertypes[m.monsterType].lag,
10);
} else } else
// track player some more // track player some more
transition(m, M_HOME, 1, transition(m, M_HOME, 1,
monstertypes[m.mtype].rate, 0); monstertypes[m.monsterType].rate,
0);
} }
} }
break; break;
@ -324,13 +327,14 @@ void
monsterpain(DynamicEntity *m, int damage, DynamicEntity *d) monsterpain(DynamicEntity *m, int damage, DynamicEntity *d)
{ {
// a monster hit us // a monster hit us
if (d.monsterstate) { if (d.monsterState) {
// guard for RL guys shooting themselves :) // guard for RL guys shooting themselves :)
if (m != d) { if (m != d) {
// don't attack straight away, first get angry // don't attack straight away, first get angry
m.anger++; m.anger++;
int anger = m.mtype == d.mtype ? m.anger / 2 : m.anger; int anger = m.monsterType == d.monsterType ? m.anger / 2
if (anger >= monstertypes[m.mtype].loyalty) : m.anger;
if (anger >= monstertypes[m.monsterType].loyalty)
// monster infight if very angry // monster infight if very angry
m.enemy = d; m.enemy = d;
} }
@ -340,20 +344,20 @@ monsterpain(DynamicEntity *m, int damage, DynamicEntity *d)
m.enemy = d; m.enemy = d;
} }
// in this state monster won't attack // in this state monster won't attack
transition(m, M_PAIN, 0, monstertypes[m.mtype].pain, 200); transition(m, M_PAIN, 0, monstertypes[m.monsterType].pain, 200);
if ((m.health -= damage) <= 0) { if ((m.health -= damage) <= 0) {
m.state = CS_DEAD; m.state = CS_DEAD;
m.lastaction = lastmillis; m.lastAction = lastmillis;
numkilled++; numkilled++;
player1.frags = numkilled; player1.frags = numkilled;
OFVector3D loc = m.o; OFVector3D loc = m.origin;
playsound(monstertypes[m.mtype].diesound, &loc); playsound(monstertypes[m.monsterType].diesound, &loc);
int remain = monstertotal - numkilled; int remain = monstertotal - numkilled;
if (remain > 0 && remain <= 5) if (remain > 0 && remain <= 5)
conoutf(@"only %d monster(s) remaining", remain); conoutf(@"only %d monster(s) remaining", remain);
} else { } else {
OFVector3D loc = m.o; OFVector3D loc = m.origin;
playsound(monstertypes[m.mtype].painsound, &loc); playsound(monstertypes[m.monsterType].painsound, &loc);
} }
} }
@ -393,14 +397,14 @@ monsterthink()
OFMakeVector3D(e.x, e.y, (float)S(e.x, e.y)->floor); OFMakeVector3D(e.x, e.y, (float)S(e.x, e.y)->floor);
for (DynamicEntity *monster in monsters) { for (DynamicEntity *monster in monsters) {
if (monster.state == CS_DEAD) { if (monster.state == CS_DEAD) {
if (lastmillis - monster.lastaction < 2000) { if (lastmillis - monster.lastAction < 2000) {
monster.move = 0; monster.move = 0;
moveplayer(monster, 1, false); moveplayer(monster, 1, false);
} }
} else { } else {
v.z += monster.eyeheight; v.z += monster.eyeHeight;
vdist(dist, t, monster.o, v); vdist(dist, t, monster.origin, v);
v.z -= monster.eyeheight; v.z -= monster.eyeHeight;
if (dist < 4) if (dist < 4)
teleport(i, monster); teleport(i, monster);
@ -418,6 +422,7 @@ monsterrender()
{ {
for (DynamicEntity *monster in monsters) for (DynamicEntity *monster in monsters)
renderclient(monster, false, renderclient(monster, false,
monstertypes[monster.mtype].mdlname, monster.mtype == 5, monstertypes[monster.monsterType].mdlname,
monstertypes[monster.mtype].mscale / 10.0f); monster.monsterType == 5,
monstertypes[monster.monsterType].mscale / 10.0f);
} }

View file

@ -17,22 +17,26 @@ plcollide(
{ {
if (o.state != CS_ALIVE) if (o.state != CS_ALIVE)
return true; return true;
const float r = o.radius + d.radius;
if (fabs(o.o.x - d.o.x) < r && fabs(o.o.y - d.o.y) < r) {
if (d.o.z - d.eyeheight < o.o.z - o.eyeheight) {
if (o.o.z - o.eyeheight < *hi)
*hi = o.o.z - o.eyeheight - 1;
} else if (o.o.z + o.aboveeye > *lo)
*lo = o.o.z + o.aboveeye + 1;
if (fabs(o.o.z - d.o.z) < o.aboveeye + d.eyeheight) const float r = o.radius + d.radius;
if (fabs(o.origin.x - d.origin.x) < r &&
fabs(o.origin.y - d.origin.y) < r) {
if (d.origin.z - d.eyeHeight < o.origin.z - o.eyeHeight) {
if (o.origin.z - o.eyeHeight < *hi)
*hi = o.origin.z - o.eyeHeight - 1;
} else if (o.origin.z + o.aboveEye > *lo)
*lo = o.origin.z + o.aboveEye + 1;
if (fabs(o.origin.z - d.origin.z) < o.aboveEye + d.eyeHeight)
return false; return false;
if (d.monsterstate) if (d.monsterState)
return false; // hack return false; // hack
*headspace = d.o.z - o.o.z - o.aboveeye - d.eyeheight; //
*headspace = d.origin.z - o.origin.z - o.aboveEye - d.eyeHeight;
if (*headspace < 0) if (*headspace < 0)
*headspace = 10; *headspace = 10;
} }
return true; return true;
} }
@ -69,11 +73,11 @@ mmcollide(DynamicEntity *d, float *hi, float *lo)
continue; continue;
const float r = mmi.rad + d.radius; const float r = mmi.rad + d.radius;
if (fabs(e.x - d.o.x) < r && fabs(e.y - d.o.y) < r) { if (fabs(e.x - d.origin.x) < r && fabs(e.y - d.origin.y) < r) {
float mmz = float mmz =
(float)(S(e.x, e.y)->floor + mmi.zoff + e.attr3); (float)(S(e.x, e.y)->floor + mmi.zoff + e.attr3);
if (d.o.z - d.eyeheight < mmz) { if (d.origin.z - d.eyeHeight < mmz) {
if (mmz < *hi) if (mmz < *hi)
*hi = mmz; *hi = mmz;
} else if (mmz + mmi.h > *lo) } else if (mmz + mmi.h > *lo)
@ -91,21 +95,21 @@ bool
collide(DynamicEntity *d, bool spawn, float drop, float rise) collide(DynamicEntity *d, bool spawn, float drop, float rise)
{ {
// figure out integer cube rectangle this entity covers in map // figure out integer cube rectangle this entity covers in map
const float fx1 = d.o.x - d.radius; const float fx1 = d.origin.x - d.radius;
const float fy1 = d.o.y - d.radius; const float fy1 = d.origin.y - d.radius;
const float fx2 = d.o.x + d.radius; const float fx2 = d.origin.x + d.radius;
const float fy2 = d.o.y + d.radius; const float fy2 = d.origin.y + d.radius;
const int x1 = fast_f2nat(fx1); const int x1 = fast_f2nat(fx1);
const int y1 = fast_f2nat(fy1); const int y1 = fast_f2nat(fy1);
const int x2 = fast_f2nat(fx2); const int x2 = fast_f2nat(fx2);
const int y2 = fast_f2nat(fy2); const int y2 = fast_f2nat(fy2);
float hi = 127, lo = -128; float hi = 127, lo = -128;
// big monsters are afraid of heights, unless angry :) // big monsters are afraid of heights, unless angry :)
float minfloor = (d.monsterstate && !spawn && d.health > 100) float minfloor = (d.monsterState && !spawn && d.health > 100)
? d.o.z - d.eyeheight - 4.5f ? d.origin.z - d.eyeHeight - 4.5f
: -1000.0f; : -1000.0f;
for (int x = x1; x <= x2; x++) for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) { for (int y = y1; y <= y2; y++) {
// collide with map // collide with map
if (OUTBORD(x, y)) if (OUTBORD(x, y))
@ -160,8 +164,9 @@ collide(DynamicEntity *d, bool spawn, float drop, float rise)
if (floor < minfloor) if (floor < minfloor)
return false; return false;
} }
}
if (hi - lo < d.eyeheight + d.aboveeye) if (hi - lo < d.eyeHeight + d.aboveEye)
return false; return false;
float headspace = 10; float headspace = 10;
@ -171,53 +176,61 @@ collide(DynamicEntity *d, bool spawn, float drop, float rise)
if (!plcollide(d, player, &headspace, &hi, &lo)) if (!plcollide(d, player, &headspace, &hi, &lo))
return false; return false;
} }
if (d != player1) if (d != player1)
if (!plcollide(d, player1, &headspace, &hi, &lo)) if (!plcollide(d, player1, &headspace, &hi, &lo))
return false; return false;
// this loop can be a performance bottleneck with many monster on a slow // this loop can be a performance bottleneck with many monster on a slow
// cpu, should replace with a blockmap but seems mostly fast enough // cpu, should replace with a blockmap but seems mostly fast enough
for (DynamicEntity *monster in getmonsters()) for (DynamicEntity *monster in getmonsters())
if (!vreject(d.o, monster.o, 7.0f) && d != monster && if (!vreject(d.origin, monster.origin, 7.0f) && d != monster &&
!plcollide(d, monster, &headspace, &hi, &lo)) !plcollide(d, monster, &headspace, &hi, &lo))
return false; return false;
headspace -= 0.01f; headspace -= 0.01f;
mmcollide(d, &hi, &lo); // collide with map models mmcollide(d, &hi, &lo); // collide with map models
if (spawn) { if (spawn) {
// just drop to floor (sideeffect) // just drop to floor (sideeffect)
d.o = OFMakeVector3D(d.o.x, d.o.y, lo + d.eyeheight); d.origin =
d.onfloor = true; OFMakeVector3D(d.origin.x, d.origin.y, lo + d.eyeHeight);
d.onFloor = true;
} else { } else {
const float space = d.o.z - d.eyeheight - lo; const float space = d.origin.z - d.eyeHeight - lo;
if (space < 0) { if (space < 0) {
if (space > -0.01) if (space > -0.01)
// stick on step // stick on step
d.o = OFMakeVector3D( d.origin = OFMakeVector3D(
d.o.x, d.o.y, lo + d.eyeheight); d.origin.x, d.origin.y, lo + d.eyeHeight);
else if (space > -1.26f) else if (space > -1.26f)
// rise thru stair // rise thru stair
d.o = d.origin = OFAddVector3D(
OFMakeVector3D(d.o.x, d.o.y, d.o.z + rise); d.origin, OFMakeVector3D(0, 0, rise));
else else
return false; return false;
} else } else
// gravity // gravity
d.o = OFMakeVector3D(d.o.x, d.o.y, d.origin = OFSubtractVector3D(d.origin,
d.o.z - min(min(drop, space), headspace)); OFMakeVector3D(
0, 0, min(min(drop, space), headspace)));
const float space2 = hi - (d.o.z + d.aboveeye); const float space2 = hi - (d.origin.z + d.aboveEye);
if (space2 < 0) { if (space2 < 0) {
if (space2 < -0.1) if (space2 < -0.1)
return false; // hack alert! return false; // hack alert!
// glue to ceiling // glue to ceiling
d.o = OFMakeVector3D(d.o.x, d.o.y, hi - d.aboveeye); d.origin = OFMakeVector3D(
d.origin.x, d.origin.y, hi - d.aboveEye);
// cancel out jumping velocity // cancel out jumping velocity
d.vel = OFMakeVector3D(d.vel.x, d.vel.y, 0); d.velocity =
OFMakeVector3D(d.velocity.x, d.velocity.y, 0);
} }
d.onfloor = d.o.z - d.eyeheight - lo < 0.001f; d.onFloor = (d.origin.z - d.eyeHeight - lo < 0.001f);
} }
return true; return true;
} }
@ -251,7 +264,7 @@ physicsframe() // optimally schedule physics frames inside the graphics frames
static void static void
moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime) moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
{ {
const bool water = hdr.waterlevel > pl.o.z - 0.5f; const bool water = (hdr.waterlevel > pl.origin.z - 0.5f);
const bool floating = (editmode && local) || pl.state == CS_EDITING; const bool floating = (editmode && local) || pl.state == CS_EDITING;
OFVector3D d; // vector of direction we ideally want to move in OFVector3D d; // vector of direction we ideally want to move in
@ -269,18 +282,18 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
d.x += (float)(pl.strafe * cos(rad(pl.yaw - 180))); d.x += (float)(pl.strafe * cos(rad(pl.yaw - 180)));
d.y += (float)(pl.strafe * sin(rad(pl.yaw - 180))); d.y += (float)(pl.strafe * sin(rad(pl.yaw - 180)));
const float speed = curtime / (water ? 2000.0f : 1000.0f) * pl.maxspeed; const float speed = curtime / (water ? 2000.0f : 1000.0f) * pl.maxSpeed;
const float friction = const float friction =
water ? 20.0f : (pl.onfloor || floating ? 6.0f : 30.0f); water ? 20.0f : (pl.onFloor || floating ? 6.0f : 30.0f);
const float fpsfric = friction / curtime * 20.0f; const float fpsfric = friction / curtime * 20.0f;
// slowly apply friction and direction to // slowly apply friction and direction to
// velocity, gives a smooth movement // velocity, gives a smooth movement
vmul(pl.vel, fpsfric - 1); vmul(pl.velocity, fpsfric - 1);
vadd(pl.vel, d); vadd(pl.velocity, d);
vdiv(pl.vel, fpsfric); vdiv(pl.velocity, fpsfric);
d = pl.vel; d = pl.velocity;
vmul(d, speed); // d is now frametime based velocity vector vmul(d, speed); // d is now frametime based velocity vector
pl.blocked = false; pl.blocked = false;
@ -288,52 +301,55 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
if (floating) { if (floating) {
// just apply velocity // just apply velocity
vadd(pl.o, d); vadd(pl.origin, d);
if (pl.jumpnext) { if (pl.jumpNext) {
pl.jumpnext = false; pl.jumpNext = false;
pl.vel = OFMakeVector3D(pl.vel.x, pl.vel.y, 2); pl.velocity =
OFMakeVector3D(pl.velocity.x, pl.velocity.y, 2);
} }
} else { } else {
// apply velocity with collision // apply velocity with collision
if (pl.onfloor || water) { if (pl.onFloor || water) {
if (pl.jumpnext) { if (pl.jumpNext) {
pl.jumpnext = false; pl.jumpNext = false;
// physics impulse upwards // physics impulse upwards
pl.vel = pl.velocity = OFMakeVector3D(
OFMakeVector3D(pl.vel.x, pl.vel.y, 1.7); pl.velocity.x, pl.velocity.y, 1.7);
// dampen velocity change even harder, gives // dampen velocity change even harder, gives
// correct water feel // correct water feel
if (water) if (water)
pl.vel = OFMakeVector3D(pl.vel.x / 8, pl.velocity = OFMakeVector3D(
pl.vel.y / 8, pl.vel.z); pl.velocity.x / 8,
pl.velocity.y / 8, pl.velocity.z);
if (local) if (local)
playsoundc(S_JUMP); playsoundc(S_JUMP);
else if (pl.monsterstate) { else if (pl.monsterState) {
OFVector3D loc = pl.o; OFVector3D loc = pl.origin;
playsound(S_JUMP, &loc); playsound(S_JUMP, &loc);
} }
} else if (pl.timeinair > 800) { } else if (pl.timeInAir > 800) {
// if we land after long time must have been a // if we land after long time must have been a
// high jump, make thud sound // high jump, make thud sound
if (local) if (local)
playsoundc(S_LAND); playsoundc(S_LAND);
else if (pl.monsterstate) { else if (pl.monsterState) {
OFVector3D loc = pl.o; OFVector3D loc = pl.origin;
playsound(S_LAND, &loc); playsound(S_LAND, &loc);
} }
} }
pl.timeinair = 0;
pl.timeInAir = 0;
} else } else
pl.timeinair += curtime; pl.timeInAir += curtime;
const float gravity = 20; const float gravity = 20;
const float f = 1.0f / moveres; const float f = 1.0f / moveres;
// incorrect, but works fine // incorrect, but works fine
float dropf = ((gravity - 1) + pl.timeinair / 15.0f); float dropf = ((gravity - 1) + pl.timeInAir / 15.0f);
// float slowly down in water // float slowly down in water
if (water) { if (water) {
dropf = 5; dropf = 5;
pl.timeinair = 0; pl.timeInAir = 0;
} }
// at high fps, gravity kicks in too fast // at high fps, gravity kicks in too fast
const float drop = dropf * curtime / gravity / 100 / moveres; const float drop = dropf * curtime / gravity / 100 / moveres;
@ -343,32 +359,39 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
loopi(moveres) // discrete steps collision detection & sliding loopi(moveres) // discrete steps collision detection & sliding
{ {
// try move forward // try move forward
pl.o = OFMakeVector3D(pl.o.x + f * d.x, pl.origin = OFAddVector3D(pl.origin,
pl.o.y + f * d.y, pl.o.z + f * d.z); OFMakeVector3D(f * d.x, f * d.y, f * d.z));
if (collide(pl, false, drop, rise)) if (collide(pl, false, drop, rise))
continue; continue;
// player stuck, try slide along y axis // player stuck, try slide along y axis
pl.blocked = true; pl.blocked = true;
pl.o = OFMakeVector3D(pl.o.x - f * d.x, pl.o.y, pl.o.z); pl.origin = OFSubtractVector3D(
pl.origin, OFMakeVector3D(f * d.x, 0, 0));
if (collide(pl, false, drop, rise)) { if (collide(pl, false, drop, rise)) {
d.x = 0; d.x = 0;
continue; continue;
} }
// still stuck, try x axis // still stuck, try x axis
pl.o = OFMakeVector3D( pl.origin = OFAddVector3D(
pl.o.x + f * d.x, pl.o.y - f * d.y, pl.o.z); pl.origin, OFMakeVector3D(f * d.x, -f * d.y, 0));
if (collide(pl, false, drop, rise)) { if (collide(pl, false, drop, rise)) {
d.y = 0; d.y = 0;
continue; continue;
} }
// try just dropping down // try just dropping down
pl.moving = false; pl.moving = false;
pl.o = OFMakeVector3D(pl.o.x - f * d.x, pl.o.y, pl.o.z); pl.origin = OFSubtractVector3D(
pl.origin, OFMakeVector3D(f * d.x, 0, 0));
if (collide(pl, false, drop, rise)) { if (collide(pl, false, drop, rise)) {
d.y = d.x = 0; d.y = d.x = 0;
continue; continue;
} }
pl.o = OFMakeVector3D(pl.o.x, pl.o.y, pl.o.z - f * d.z);
pl.origin = OFSubtractVector3D(
pl.origin, OFMakeVector3D(0, 0, f * d.z));
break; break;
} }
} }
@ -376,13 +399,16 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
// detect wether player is outside map, used for skipping zbuffer clear // detect wether player is outside map, used for skipping zbuffer clear
// mostly // mostly
if (pl.o.x < 0 || pl.o.x >= ssize || pl.o.y < 0 || pl.o.y > ssize) if (pl.origin.x < 0 || pl.origin.x >= ssize || pl.origin.y < 0 ||
pl.outsidemap = true; pl.origin.y > ssize)
pl.outsideMap = true;
else { else {
struct sqr *s = S((int)pl.o.x, (int)pl.o.y); struct sqr *s = S((int)pl.origin.x, (int)pl.origin.y);
pl.outsidemap = SOLID(s) || pl.outsideMap = SOLID(s) ||
pl.o.z < s->floor - (s->type == FHF ? s->vdelta / 4 : 0) || pl.origin.z <
pl.o.z > s->ceil + (s->type == CHF ? s->vdelta / 4 : 0); s->floor - (s->type == FHF ? s->vdelta / 4 : 0) ||
pl.origin.z >
s->ceil + (s->type == CHF ? s->vdelta / 4 : 0);
} }
// automatically apply smooth roll when strafing // automatically apply smooth roll when strafing
@ -399,15 +425,15 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
// play sounds on water transitions // play sounds on water transitions
if (!pl.inwater && water) { if (!pl.inWater && water) {
OFVector3D loc = pl.o; OFVector3D loc = pl.origin;
playsound(S_SPLASH2, &loc); playsound(S_SPLASH2, &loc);
pl.vel = OFMakeVector3D(pl.vel.x, pl.vel.y, 0); pl.velocity = OFMakeVector3D(pl.velocity.x, pl.velocity.y, 0);
} else if (pl.inwater && !water) { } else if (pl.inWater && !water) {
OFVector3D loc = pl.o; OFVector3D loc = pl.origin;
playsound(S_SPLASH1, &loc); playsound(S_SPLASH1, &loc);
} }
pl.inwater = water; pl.inWater = water;
} }
void void

View file

@ -100,13 +100,11 @@ extern void changemap(OFString *name);
extern void initclient(); extern void initclient();
extern void spawnplayer(DynamicEntity *d); extern void spawnplayer(DynamicEntity *d);
extern void selfdamage(int damage, int actor, DynamicEntity *act); extern void selfdamage(int damage, int actor, DynamicEntity *act);
extern DynamicEntity *newdynent();
extern OFString *getclientmap(); extern OFString *getclientmap();
extern OFString *modestr(int n); extern OFString *modestr(int n);
extern DynamicEntity *getclient(int cn); extern DynamicEntity *getclient(int cn);
extern void setclient(int cn, id client); extern void setclient(int cn, id client);
extern void timeupdate(int timeremain); extern void timeupdate(int timeremain);
extern void resetmovement(DynamicEntity *d);
extern void fixplayer1range(); extern void fixplayer1range();
// clientextras // clientextras

View file

@ -335,7 +335,7 @@ gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
readmatrices(); readmatrices();
if (editmode) { if (editmode) {
if (cursordepth == 1.0f) if (cursordepth == 1.0f)
worldpos = player1.o; worldpos = player1.origin;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
cursorupdate(); cursorupdate();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@ -385,7 +385,7 @@ gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
glBegin(GL_QUADS); glBegin(GL_QUADS);
glColor3ub(255, 255, 255); glColor3ub(255, 255, 255);
if (crosshairfx) { if (crosshairfx) {
if (player1.gunwait) if (player1.gunWait)
glColor3ub(128, 128, 128); glColor3ub(128, 128, 128);
else if (player1.health <= 25) else if (player1.health <= 25)
glColor3ub(255, 0, 0); glColor3ub(255, 0, 0);
@ -428,7 +428,7 @@ gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
draw_textf(@"%d", 90, 827, 2, player1.health); draw_textf(@"%d", 90, 827, 2, player1.health);
if (player1.armour) if (player1.armour)
draw_textf(@"%d", 390, 827, 2, player1.armour); draw_textf(@"%d", 390, 827, 2, player1.armour);
draw_textf(@"%d", 690, 827, 2, player1.ammo[player1.gunselect]); draw_textf(@"%d", 690, 827, 2, player1.ammo[player1.gunSelect]);
glPopMatrix(); glPopMatrix();
glPushMatrix(); glPushMatrix();
glOrtho(0, VIRTW, VIRTH, 0, -1, 1); glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
@ -436,8 +436,8 @@ gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
drawicon(128, 128, 20, 1650); drawicon(128, 128, 20, 1650);
if (player1.armour) if (player1.armour)
drawicon( drawicon(
(float)(player1.armourtype * 64), 0, 620, 1650); (float)(player1.armourType * 64), 0, 620, 1650);
int g = player1.gunselect; int g = player1.gunSelect;
int r = 64; int r = 64;
if (g > 2) { if (g > 2) {
g -= 3; g -= 3;

View file

@ -350,10 +350,10 @@ transplayer()
glRotated(player1.pitch, -1.0, 0.0, 0.0); glRotated(player1.pitch, -1.0, 0.0, 0.0);
glRotated(player1.yaw, 0.0, 1.0, 0.0); glRotated(player1.yaw, 0.0, 1.0, 0.0);
glTranslated(-player1.o.x, glTranslated(-player1.origin.x,
(player1.state == CS_DEAD ? player1.eyeheight - 0.2f : 0) - (player1.state == CS_DEAD ? player1.eyeHeight - 0.2f : 0) -
player1.o.z, player1.origin.z,
-player1.o.y); -player1.origin.y);
} }
VARP(fov, 10, 105, 120); VARP(fov, 10, 105, 120);
@ -371,15 +371,16 @@ OFString *hudgunnames[] = { @"hudguns/fist", @"hudguns/shotg",
void void
drawhudmodel(int start, int end, float speed, int base) drawhudmodel(int start, int end, float speed, int base)
{ {
rendermodel(hudgunnames[player1.gunselect], start, end, 0, 1.0f, rendermodel(hudgunnames[player1.gunSelect], start, end, 0, 1.0f,
OFMakeVector3D(player1.o.x, player1.o.z, player1.o.y), OFMakeVector3D(
player1.origin.x, player1.origin.z, player1.origin.y),
player1.yaw + 90, player1.pitch, false, 1.0f, speed, 0, base); player1.yaw + 90, player1.pitch, false, 1.0f, speed, 0, base);
} }
void void
drawhudgun(float fovy, float aspect, int farplane) drawhudgun(float fovy, float aspect, int farplane)
{ {
if (!hudgun /*|| !player1.gunselect*/) if (!hudgun /*|| !player1.gunSelect*/)
return; return;
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@ -390,10 +391,10 @@ drawhudgun(float fovy, float aspect, int farplane)
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
// glClear(GL_DEPTH_BUFFER_BIT); // glClear(GL_DEPTH_BUFFER_BIT);
int rtime = reloadtime(player1.gunselect); int rtime = reloadtime(player1.gunSelect);
if (player1.lastaction && player1.lastattackgun == player1.gunselect && if (player1.lastAction && player1.lastAttackGun == player1.gunSelect &&
lastmillis - player1.lastaction < rtime) { lastmillis - player1.lastAction < rtime) {
drawhudmodel(7, 18, rtime / 18.0f, player1.lastaction); drawhudmodel(7, 18, rtime / 18.0f, player1.lastAction);
} else } else
drawhudmodel(6, 1, 100, 0); drawhudmodel(6, 1, 100, 0);
@ -411,7 +412,7 @@ gl_drawframe(int w, int h, float curfps)
float hf = hdr.waterlevel - 0.3f; float hf = hdr.waterlevel - 0.3f;
float fovy = (float)fov * h / w; float fovy = (float)fov * h / w;
float aspect = w / (float)h; float aspect = w / (float)h;
bool underwater = player1.o.z < hf; bool underwater = (player1.origin.z < hf);
glFogi(GL_FOG_START, (fog + 64) / 8); glFogi(GL_FOG_START, (fog + 64) / 8);
glFogi(GL_FOG_END, fog); glFogi(GL_FOG_END, fog);
@ -428,7 +429,7 @@ gl_drawframe(int w, int h, float curfps)
glFogi(GL_FOG_END, (fog + 96) / 8); glFogi(GL_FOG_END, (fog + 96) / 8);
} }
glClear((player1.outsidemap ? GL_COLOR_BUFFER_BIT : 0) | glClear((player1.outsideMap ? GL_COLOR_BUFFER_BIT : 0) |
GL_DEPTH_BUFFER_BIT); GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -449,8 +450,8 @@ gl_drawframe(int w, int h, float curfps)
curvert = 0; curvert = 0;
[strips removeAllItems]; [strips removeAllItems];
render_world(player1.o.x, player1.o.y, player1.o.z, (int)player1.yaw, render_world(player1.origin.x, player1.origin.y, player1.origin.z,
(int)player1.pitch, (float)fov, w, h); (int)player1.yaw, (int)player1.pitch, (float)fov, w, h);
finishstrips(); finishstrips();
gl_setupworld(); gl_setupworld();

View file

@ -93,7 +93,7 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
{ {
MD2 *m = loadmodel(mdl); MD2 *m = loadmodel(mdl);
if (isoccluded(player1.o.x, player1.o.y, position.x - rad, if (isoccluded(player1.origin.x, player1.origin.y, position.x - rad,
position.z - rad, rad * 2)) position.z - rad, rad * 2))
return; return;

View file

@ -57,7 +57,7 @@ void
render_particles(int time) render_particles(int time)
{ {
if (demoplayback && demotracking) { if (demoplayback && demotracking) {
OFVector3D o = player1.o; OFVector3D o = player1.origin;
OFVector3D nom = OFMakeVector3D(0, 0, 0); OFVector3D nom = OFMakeVector3D(0, 0, 0);
newparticle(&o, &nom, 100000000, 8); newparticle(&o, &nom, 100000000, 8);
} }

View file

@ -224,7 +224,7 @@ loadgamerest()
[data increaseCountBy:DynamicEntity.serializedSize]; [data increaseCountBy:DynamicEntity.serializedSize];
gzread(f, data.mutableItems, data.count); gzread(f, data.mutableItems, data.count);
[player1 setFromSerializedData:data]; [player1 setFromSerializedData:data];
player1.lastaction = lastmillis; player1.lastAction = lastmillis;
int nmonsters = gzgeti(); int nmonsters = gzgeti();
OFArray<DynamicEntity *> *monsters = getmonsters(); OFArray<DynamicEntity *> *monsters = getmonsters();
@ -237,9 +237,9 @@ loadgamerest()
// lazy, could save id of enemy instead // lazy, could save id of enemy instead
monster.enemy = player1; monster.enemy = player1;
// also lazy, but no real noticable effect on game // also lazy, but no real noticable effect on game
monster.lastaction = monster.trigger = lastmillis + 500; monster.lastAction = monster.trigger = lastmillis + 500;
if (monster.state == CS_DEAD) if (monster.state == CS_DEAD)
monster.lastaction = 0; monster.lastAction = 0;
} }
restoremonsterstate(); restoremonsterstate();
@ -313,13 +313,13 @@ incomingdemodata(uchar *buf, int len, bool extras)
gzwrite(f, buf, len); gzwrite(f, buf, len);
gzput(extras); gzput(extras);
if (extras) { if (extras) {
gzput(player1.gunselect); gzput(player1.gunSelect);
gzput(player1.lastattackgun); gzput(player1.lastAttackGun);
gzputi(player1.lastaction - starttime); gzputi(player1.lastAction - starttime);
gzputi(player1.gunwait); gzputi(player1.gunWait);
gzputi(player1.health); gzputi(player1.health);
gzputi(player1.armour); gzputi(player1.armour);
gzput(player1.armourtype); gzput(player1.armourType);
loopi(NUMGUNS) gzput(player1.ammo[i]); loopi(NUMGUNS) gzput(player1.ammo[i]);
gzput(player1.state); gzput(player1.state);
gzputi(bdamage); gzputi(bdamage);
@ -440,16 +440,16 @@ demoplaybackstep()
// read additional client side state not present in normal // read additional client side state not present in normal
// network stream // network stream
if ((extras = gzget())) { if ((extras = gzget())) {
target.gunselect = gzget(); target.gunSelect = gzget();
target.lastattackgun = gzget(); target.lastAttackGun = gzget();
target.lastaction = scaletime(gzgeti()); target.lastAction = scaletime(gzgeti());
target.gunwait = gzgeti(); target.gunWait = gzgeti();
target.health = gzgeti(); target.health = gzgeti();
target.armour = gzgeti(); target.armour = gzgeti();
target.armourtype = gzget(); target.armourType = gzget();
loopi(NUMGUNS) target.ammo[i] = gzget(); loopi(NUMGUNS) target.ammo[i] = gzget();
target.state = gzget(); target.state = gzget();
target.lastmove = playbacktime; target.lastMove = playbacktime;
if ((bdamage = gzgeti())) if ((bdamage = gzgeti()))
damageblend(bdamage); damageblend(bdamage);
if ((ddamage = gzgeti())) { if ((ddamage = gzgeti())) {
@ -462,9 +462,9 @@ demoplaybackstep()
// insert latest copy of player into history // insert latest copy of player into history
if (extras && if (extras &&
(playerhistory.count == 0 || (playerhistory.count == 0 ||
playerhistory.lastObject.lastupdate != playbacktime)) { playerhistory.lastObject.lastUpdate != playbacktime)) {
DynamicEntity *d = [target copy]; DynamicEntity *d = [target copy];
d.lastupdate = playbacktime; d.lastUpdate = playbacktime;
if (playerhistory == nil) if (playerhistory == nil)
playerhistory = [[OFMutableArray alloc] init]; playerhistory = [[OFMutableArray alloc] init];
@ -485,7 +485,7 @@ demoplaybackstep()
// find 2 positions in history that surround interpolation time point // find 2 positions in history that surround interpolation time point
size_t count = playerhistory.count; size_t count = playerhistory.count;
for (ssize_t i = count - 1; i >= 0; i--) { for (ssize_t i = count - 1; i >= 0; i--) {
if (playerhistory[i].lastupdate < itime) { if (playerhistory[i].lastUpdate < itime) {
DynamicEntity *a = playerhistory[i]; DynamicEntity *a = playerhistory[i];
DynamicEntity *b = a; DynamicEntity *b = a;
@ -503,16 +503,16 @@ demoplaybackstep()
z = playerhistory[i - 1]; z = playerhistory[i - 1];
// if(a==z || b==c) // if(a==z || b==c)
// printf("* %d\n", lastmillis); // printf("* %d\n", lastmillis);
float bf = (itime - a.lastupdate) / float bf = (itime - a.lastUpdate) /
(float)(b.lastupdate - a.lastupdate); (float)(b.lastUpdate - a.lastUpdate);
fixwrap(a, player1); fixwrap(a, player1);
fixwrap(c, player1); fixwrap(c, player1);
fixwrap(z, player1); fixwrap(z, player1);
vdist(dist, v, z.o, c.o); vdist(dist, v, z.origin, c.origin);
// if teleport or spawn, don't interpolate // if teleport or spawn, don't interpolate
if (dist < 16) { if (dist < 16) {
catmulrom( catmulrom(z.origin, a.origin, b.origin,
z.o, a.o, b.o, c.o, bf, player1.o); c.origin, bf, player1.origin);
OFVector3D vz = OFMakeVector3D( OFVector3D vz = OFMakeVector3D(
z.yaw, z.pitch, z.roll); z.yaw, z.pitch, z.roll);
OFVector3D va = OFMakeVector3D( OFVector3D va = OFMakeVector3D(

View file

@ -117,7 +117,7 @@ updatechanvol(int chan, const OFVector3D *loc)
{ {
int vol = soundvol, pan = 255 / 2; int vol = soundvol, pan = 255 / 2;
if (loc) { if (loc) {
vdist(dist, v, *loc, player1.o); vdist(dist, v, *loc, player1.origin);
vol -= (int)(dist * 3 * soundvol / vol -= (int)(dist * 3 * soundvol /
255); // simple mono distance attenuation 255); // simple mono distance attenuation
if (stereo && (v.x != 0 || v.y != 0)) { if (stereo && (v.x != 0 || v.y != 0)) {

View file

@ -32,7 +32,7 @@ selectgun(int a, int b, int c)
if (a < -1 || b < -1 || c < -1 || a >= NUMGUNS || b >= NUMGUNS || if (a < -1 || b < -1 || c < -1 || a >= NUMGUNS || b >= NUMGUNS ||
c >= NUMGUNS) c >= NUMGUNS)
return; return;
int s = player1.gunselect; int s = player1.gunSelect;
if (a >= 0 && s != a && player1.ammo[a]) if (a >= 0 && s != a && player1.ammo[a])
s = a; s = a;
else if (b >= 0 && s != b && player1.ammo[b]) else if (b >= 0 && s != b && player1.ammo[b])
@ -49,9 +49,9 @@ selectgun(int a, int b, int c)
s = GUN_RIFLE; s = GUN_RIFLE;
else else
s = GUN_FIST; s = GUN_FIST;
if (s != player1.gunselect) if (s != player1.gunSelect)
playsoundc(S_WEAPLOAD); playsoundc(S_WEAPLOAD);
player1.gunselect = s; player1.gunSelect = s;
// conoutf(@"%@ selected", (int)guns[s].name); // conoutf(@"%@ selected", (int)guns[s].name);
} }
@ -89,7 +89,7 @@ createrays(const OFVector3D *from, const OFVector3D *to)
static bool static bool
intersect(DynamicEntity *d, const OFVector3D *from, const OFVector3D *to) intersect(DynamicEntity *d, const OFVector3D *from, const OFVector3D *to)
{ {
OFVector3D v = *to, w = d.o; OFVector3D v = *to, w = d.origin;
const OFVector3D *p; const OFVector3D *p;
vsub(v, *from); vsub(v, *from);
vsub(w, *from); vsub(w, *from);
@ -109,9 +109,10 @@ intersect(DynamicEntity *d, const OFVector3D *from, const OFVector3D *to)
} }
} }
return (p->x <= d.o.x + d.radius && p->x >= d.o.x - d.radius && return (p->x <= d.origin.x + d.radius &&
p->y <= d.o.y + d.radius && p->y >= d.o.y - d.radius && p->x >= d.origin.x - d.radius && p->y <= d.origin.y + d.radius &&
p->z <= d.o.z + d.aboveeye && p->z >= d.o.z - d.eyeheight); p->y >= d.origin.y - d.radius && p->z <= d.origin.z + d.aboveEye &&
p->z >= d.origin.z - d.eyeHeight);
} }
OFString * OFString *
@ -124,7 +125,7 @@ playerincrosshair()
if (player == [OFNull null]) if (player == [OFNull null])
continue; continue;
OFVector3D o = player1.o; OFVector3D o = player1.origin;
if (intersect(player, &o, &worldpos)) if (intersect(player, &o, &worldpos))
return [player name]; return [player name];
} }
@ -169,13 +170,13 @@ newprojectile(const OFVector3D *from, const OFVector3D *to, float speed,
void void
hit(int target, int damage, DynamicEntity *d, DynamicEntity *at) hit(int target, int damage, DynamicEntity *d, DynamicEntity *at)
{ {
OFVector3D o = d.o; OFVector3D o = d.origin;
if (d == player1) if (d == player1)
selfdamage(damage, at == player1 ? -1 : -2, at); selfdamage(damage, at == player1 ? -1 : -2, at);
else if (d.monsterstate) else if (d.monsterState)
monsterpain(d, damage, at); monsterpain(d, damage, at);
else { else {
addmsg(1, 4, SV_DAMAGE, target, damage, d.lifesequence); addmsg(1, 4, SV_DAMAGE, target, damage, d.lifeSequence);
playsound(S_PAIN1 + rnd(5), &o); playsound(S_PAIN1 + rnd(5), &o);
} }
particle_splash(3, damage, 1000, &o); particle_splash(3, damage, 1000, &o);
@ -191,7 +192,7 @@ radialeffect(
{ {
if (o.state != CS_ALIVE) if (o.state != CS_ALIVE)
return; return;
vdist(dist, temp, *v, o.o); vdist(dist, temp, *v, o.origin);
dist -= 2; // account for eye distance imprecision dist -= 2; // account for eye distance imprecision
if (dist < RL_DAMRAD) { if (dist < RL_DAMRAD) {
if (dist < 0) if (dist < 0)
@ -199,7 +200,7 @@ radialeffect(
int damage = (int)(qdam * (1 - (dist / RL_DAMRAD))); int damage = (int)(qdam * (1 - (dist / RL_DAMRAD)));
hit(cn, damage, o, at); hit(cn, damage, o, at);
vmul(temp, (RL_DAMRAD - dist) * damage / 800); vmul(temp, (RL_DAMRAD - dist) * damage / 800);
vadd(o.vel, temp); vadd(o.velocity, temp);
} }
} }
@ -265,8 +266,8 @@ moveprojectiles(float time)
if (!p.inuse) if (!p.inuse)
continue; continue;
int qdam = guns[p.gun].damage * (p.owner.quadmillis ? 4 : 1); int qdam = guns[p.gun].damage * (p.owner.quadMillis ? 4 : 1);
if (p.owner.monsterstate) if (p.owner.monsterState)
qdam /= MONSTERDAMAGEFACTOR; qdam /= MONSTERDAMAGEFACTOR;
vdist(dist, v, p.o, p.to); vdist(dist, v, p.o, p.to);
float dtime = dist * 1000 / p.speed; float dtime = dist * 1000 / p.speed;
@ -283,7 +284,7 @@ moveprojectiles(float time)
projdamage(player1, p, &v, -1, -1, qdam); projdamage(player1, p, &v, -1, -1, qdam);
for (DynamicEntity *monster in getmonsters()) for (DynamicEntity *monster in getmonsters())
if (!vreject(monster.o, v, 10.0f) && if (!vreject(monster.origin, v, 10.0f) &&
monster != p.owner) monster != p.owner)
projdamage(monster, p, &v, -1, i, qdam); projdamage(monster, p, &v, -1, i, qdam);
} }
@ -312,7 +313,7 @@ void
shootv(int gun, const OFVector3D *from, const OFVector3D *to, DynamicEntity *d, shootv(int gun, const OFVector3D *from, const OFVector3D *to, DynamicEntity *d,
bool local) bool local)
{ {
OFVector3D loc = d.o; OFVector3D loc = d.origin;
playsound(guns[gun].sound, d == player1 ? NULL : &loc); playsound(guns[gun].sound, d == player1 ? NULL : &loc);
int pspeed = 25; int pspeed = 25;
switch (gun) { switch (gun) {
@ -334,7 +335,7 @@ shootv(int gun, const OFVector3D *from, const OFVector3D *to, DynamicEntity *d,
case GUN_ICEBALL: case GUN_ICEBALL:
case GUN_SLIMEBALL: case GUN_SLIMEBALL:
pspeed = guns[gun].projspeed; pspeed = guns[gun].projspeed;
if (d.monsterstate) if (d.monsterState)
pspeed /= 2; pspeed /= 2;
newprojectile(from, to, (float)pspeed, local, d, gun); newprojectile(from, to, (float)pspeed, local, d, gun);
break; break;
@ -353,7 +354,7 @@ hitpush(int target, int damage, DynamicEntity *d, DynamicEntity *at,
hit(target, damage, d, at); hit(target, damage, d, at);
vdist(dist, v, *from, *to); vdist(dist, v, *from, *to);
vmul(v, damage / dist / 50); vmul(v, damage / dist / 50);
vadd(d.vel, v); vadd(d.velocity, v);
} }
void void
@ -362,12 +363,12 @@ raydamage(DynamicEntity *o, const OFVector3D *from, const OFVector3D *to,
{ {
if (o.state != CS_ALIVE) if (o.state != CS_ALIVE)
return; return;
int qdam = guns[d.gunselect].damage; int qdam = guns[d.gunSelect].damage;
if (d.quadmillis) if (d.quadMillis)
qdam *= 4; qdam *= 4;
if (d.monsterstate) if (d.monsterState)
qdam /= MONSTERDAMAGEFACTOR; qdam /= MONSTERDAMAGEFACTOR;
if (d.gunselect == GUN_SG) { if (d.gunSelect == GUN_SG) {
int damage = 0; int damage = 0;
loop(r, SGRAYS) if (intersect(o, from, &sg[r])) damage += qdam; loop(r, SGRAYS) if (intersect(o, from, &sg[r])) damage += qdam;
if (damage) if (damage)
@ -379,52 +380,52 @@ raydamage(DynamicEntity *o, const OFVector3D *from, const OFVector3D *to,
void void
shoot(DynamicEntity *d, const OFVector3D *targ) shoot(DynamicEntity *d, const OFVector3D *targ)
{ {
int attacktime = lastmillis - d.lastaction; int attacktime = lastmillis - d.lastAction;
if (attacktime < d.gunwait) if (attacktime < d.gunWait)
return; return;
d.gunwait = 0; d.gunWait = 0;
if (!d.attacking) if (!d.attacking)
return; return;
d.lastaction = lastmillis; d.lastAction = lastmillis;
d.lastattackgun = d.gunselect; d.lastAttackGun = d.gunSelect;
if (!d.ammo[d.gunselect]) { if (!d.ammo[d.gunSelect]) {
playsoundc(S_NOAMMO); playsoundc(S_NOAMMO);
d.gunwait = 250; d.gunWait = 250;
d.lastattackgun = -1; d.lastAttackGun = -1;
return; return;
} }
if (d.gunselect) if (d.gunSelect)
d.ammo[d.gunselect]--; d.ammo[d.gunSelect]--;
OFVector3D from = d.o; OFVector3D from = d.origin;
OFVector3D to = *targ; OFVector3D to = *targ;
from.z -= 0.2f; // below eye from.z -= 0.2f; // below eye
vdist(dist, unitv, from, to); vdist(dist, unitv, from, to);
vdiv(unitv, dist); vdiv(unitv, dist);
OFVector3D kickback = unitv; OFVector3D kickback = unitv;
vmul(kickback, guns[d.gunselect].kickamount * -0.01f); vmul(kickback, guns[d.gunSelect].kickamount * -0.01f);
vadd(d.vel, kickback); vadd(d.velocity, kickback);
if (d.pitch < 80.0f) if (d.pitch < 80.0f)
d.pitch += guns[d.gunselect].kickamount * 0.05f; d.pitch += guns[d.gunSelect].kickamount * 0.05f;
if (d.gunselect == GUN_FIST || d.gunselect == GUN_BITE) { if (d.gunSelect == GUN_FIST || d.gunSelect == GUN_BITE) {
vmul(unitv, 3); // punch range vmul(unitv, 3); // punch range
to = from; to = from;
vadd(to, unitv); vadd(to, unitv);
} }
if (d.gunselect == GUN_SG) if (d.gunSelect == GUN_SG)
createrays(&from, &to); createrays(&from, &to);
if (d.quadmillis && attacktime > 200) if (d.quadMillis && attacktime > 200)
playsoundc(S_ITEMPUP); playsoundc(S_ITEMPUP);
shootv(d.gunselect, &from, &to, d, true); shootv(d.gunSelect, &from, &to, d, true);
if (!d.monsterstate) if (!d.monsterState)
addmsg(1, 8, SV_SHOT, d.gunselect, (int)(from.x * DMF), addmsg(1, 8, SV_SHOT, d.gunSelect, (int)(from.x * DMF),
(int)(from.y * DMF), (int)(from.z * DMF), (int)(to.x * DMF), (int)(from.y * DMF), (int)(from.z * DMF), (int)(to.x * DMF),
(int)(to.y * DMF), (int)(to.z * DMF)); (int)(to.y * DMF), (int)(to.z * DMF));
d.gunwait = guns[d.gunselect].attackdelay; d.gunWait = guns[d.gunSelect].attackdelay;
if (guns[d.gunselect].projspeed) if (guns[d.gunSelect].projspeed)
return; return;
[players enumerateObjectsUsingBlock:^(id player, size_t i, bool *stop) { [players enumerateObjectsUsingBlock:^(id player, size_t i, bool *stop) {
@ -436,6 +437,6 @@ shoot(DynamicEntity *d, const OFVector3D *targ)
if (monster != d) if (monster != d)
raydamage(monster, &from, &to, d, -2); raydamage(monster, &from, &to, d, -2);
if (d.monsterstate) if (d.monsterState)
raydamage(player1, &from, &to, d, -1); raydamage(player1, &from, &to, d, -1);
} }

View file

@ -270,7 +270,7 @@ closestent() // used for delent and edit mode ent display
return; return;
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z); OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
vdist(dist, t, player1.o, v); vdist(dist, t, player1.origin, v);
if (dist < bdist) { if (dist < bdist) {
best = i; best = i;
bdist = dist; bdist = dist;

View file

@ -205,7 +205,7 @@ dodynlight(const OFVector3D *vold, const OFVector3D *v, int reach, int strength,
{ {
if (!reach) if (!reach)
reach = dynlight; reach = dynlight;
if (owner.monsterstate) if (owner.monsterState)
reach = reach / 2; reach = reach / 2;
if (!reach) if (!reach)
return; return;

View file

@ -137,7 +137,7 @@ render_seg_new(
// first collect occlusion information for this block // first collect occlusion information for this block
for (int oy = y; oy < ys; oy++) { for (int oy = y; oy < ys; oy++) {
SWS(w, ox, oy, sz)->occluded = SWS(w, ox, oy, sz)->occluded =
isoccluded(player1.o.x, player1.o.y, isoccluded(player1.origin.x, player1.origin.y,
(float)(ox << mip), (float)(oy << mip), fsize); (float)(ox << mip), (float)(oy << mip), fsize);
} }
} }