Clean up DynamicEntity
FossilOrigin-Name: b787ad5a04fc238a69b9e48b3bdfccde416f636a021eef0d955445b5ab92252b
This commit is contained in:
parent
fd2b1dddf0
commit
a7db00c740
24 changed files with 561 additions and 540 deletions
|
@ -232,7 +232,7 @@ VARP(minmillis, 0, 5, 1000);
|
|||
static float fps = 30.0f;
|
||||
fps = (1000.0f / curtime + fps * 50) / 51;
|
||||
|
||||
computeraytable(player1.o.x, player1.o.y);
|
||||
computeraytable(player1.origin.x, player1.origin.y);
|
||||
readdepth(_width, _height);
|
||||
SDL_GL_SwapWindow(_window);
|
||||
extern void updatevol();
|
||||
|
|
|
@ -4,52 +4,55 @@
|
|||
@interface DynamicEntity: OFObject <OFCopying>
|
||||
@property (class, readonly, nonatomic) size_t serializedSize;
|
||||
|
||||
// origin, velocity
|
||||
@property (nonatomic) OFVector3D o, vel;
|
||||
@property (nonatomic) OFVector3D origin, velocity;
|
||||
// used as OFVector3D in one place
|
||||
@property (nonatomic) float yaw, pitch, roll;
|
||||
// cubes per second, 24 for player
|
||||
@property (nonatomic) float maxspeed;
|
||||
@property (nonatomic) float maxSpeed;
|
||||
// from his eyes
|
||||
@property (nonatomic) bool outsidemap;
|
||||
@property (nonatomic) bool inwater;
|
||||
@property (nonatomic) bool onfloor, jumpnext;
|
||||
@property (nonatomic) bool outsideMap;
|
||||
@property (nonatomic) bool inWater;
|
||||
@property (nonatomic) bool onFloor, jumpNext;
|
||||
@property (nonatomic) int move, strafe;
|
||||
// see input code
|
||||
@property (nonatomic) bool k_left, k_right, k_up, k_down;
|
||||
// used for fake gravity
|
||||
@property (nonatomic) int timeinair;
|
||||
@property (nonatomic) int timeInAir;
|
||||
// bounding box size
|
||||
@property (nonatomic) float radius, eyeheight, aboveeye;
|
||||
@property (nonatomic) int lastupdate, plag, ping;
|
||||
@property (nonatomic) float radius, eyeHeight, aboveEye;
|
||||
@property (nonatomic) int lastUpdate, lag, ping;
|
||||
// sequence id for each respawn, used in damage test
|
||||
@property (nonatomic) int lifesequence;
|
||||
@property (nonatomic) int lifeSequence;
|
||||
// one of CS_* below
|
||||
@property (nonatomic) int state;
|
||||
@property (nonatomic) int frags;
|
||||
@property (nonatomic) int health, armour, armourtype, quadmillis;
|
||||
@property (nonatomic) int gunselect, gunwait;
|
||||
@property (nonatomic) int lastaction, lastattackgun, lastmove;
|
||||
@property (nonatomic) int health, armour, armourType, quadMillis;
|
||||
@property (nonatomic) int gunSelect, gunWait;
|
||||
@property (nonatomic) int lastAction, lastAttackGun, lastMove;
|
||||
@property (nonatomic) bool attacking;
|
||||
@property (readonly, nonatomic) int *ammo;
|
||||
// one of M_* below, M_NONE means human
|
||||
@property (nonatomic) int monsterstate;
|
||||
// see monster.cpp
|
||||
@property (nonatomic) int mtype;
|
||||
@property (nonatomic) int monsterState;
|
||||
// see monster.m
|
||||
@property (nonatomic) int monsterType;
|
||||
// monster wants to kill this entity
|
||||
@property (nonatomic) DynamicEntity *enemy;
|
||||
// monster wants to look in this direction
|
||||
@property (nonatomic) float targetyaw;
|
||||
@property (nonatomic) float targetYaw;
|
||||
// used by physics to signal ai
|
||||
@property (nonatomic) bool blocked, moving;
|
||||
// millis at which transition to another monsterstate takes place
|
||||
@property (nonatomic) int trigger;
|
||||
// delayed attacks
|
||||
@property (nonatomic) OFVector3D attacktarget;
|
||||
@property (nonatomic) OFVector3D attackTarget;
|
||||
// how many times already hit by fellow monster
|
||||
@property (nonatomic) int anger;
|
||||
@property (copy, nonatomic) OFString *name, *team;
|
||||
|
||||
+ (instancetype)entity;
|
||||
- (OFData *)dataBySerializing;
|
||||
- (void)setFromSerializedData:(OFData *)data;
|
||||
- (void)resetMovement;
|
||||
// reset player state not persistent accross spawns
|
||||
- (void)resetToSpawnState;
|
||||
@end
|
||||
|
|
|
@ -3,37 +3,42 @@
|
|||
#include "cube.h"
|
||||
|
||||
struct dynent {
|
||||
OFVector3D o, vel;
|
||||
OFVector3D origin, velocity;
|
||||
float yaw, pitch, roll;
|
||||
float maxspeed;
|
||||
bool outsidemap;
|
||||
bool inwater;
|
||||
bool onfloor, jumpnext;
|
||||
float maxSpeed;
|
||||
bool outsideMap;
|
||||
bool inWater;
|
||||
bool onFloor, jumpNext;
|
||||
int move, strafe;
|
||||
bool k_left, k_right, k_up, k_down;
|
||||
int timeinair;
|
||||
float radius, eyeheight, aboveeye;
|
||||
int lastupdate, plag, ping;
|
||||
int lifesequence;
|
||||
int timeInAir;
|
||||
float radius, eyeHeight, aboveEye;
|
||||
int lastUpdate, lag, ping;
|
||||
int lifeSequence;
|
||||
int state;
|
||||
int frags;
|
||||
int health, armour, armourtype, quadmillis;
|
||||
int gunselect, gunwait;
|
||||
int lastaction, lastattackgun, lastmove;
|
||||
int health, armour, armourType, quadMillis;
|
||||
int gunSelect, gunWait;
|
||||
int lastAction, lastAttackGun, lastMove;
|
||||
bool attacking;
|
||||
int ammo[NUMGUNS];
|
||||
int monsterstate;
|
||||
int mtype;
|
||||
int monsterState;
|
||||
int monsterType;
|
||||
void *enemy;
|
||||
float targetyaw;
|
||||
float targetYaw;
|
||||
bool blocked, moving;
|
||||
int trigger;
|
||||
OFVector3D attacktarget;
|
||||
OFVector3D attackTarget;
|
||||
int anger;
|
||||
char name[260], team[260];
|
||||
};
|
||||
|
||||
@implementation DynamicEntity
|
||||
+ (instancetype)entity
|
||||
{
|
||||
return [[self alloc] init];
|
||||
}
|
||||
|
||||
+ (size_t)serializedSize
|
||||
{
|
||||
return sizeof(struct dynent);
|
||||
|
@ -45,6 +50,17 @@ struct dynent {
|
|||
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -57,54 +73,54 @@ struct dynent {
|
|||
{
|
||||
DynamicEntity *copy = [[self.class alloc] init];
|
||||
|
||||
copy->_o = _o;
|
||||
copy->_vel = _vel;
|
||||
copy->_origin = _origin;
|
||||
copy->_velocity = _velocity;
|
||||
copy->_yaw = _yaw;
|
||||
copy->_pitch = _pitch;
|
||||
copy->_roll = _roll;
|
||||
copy->_maxspeed = _maxspeed;
|
||||
copy->_outsidemap = _outsidemap;
|
||||
copy->_inwater = _inwater;
|
||||
copy->_onfloor = _onfloor;
|
||||
copy->_jumpnext = _jumpnext;
|
||||
copy->_maxSpeed = _maxSpeed;
|
||||
copy->_outsideMap = _outsideMap;
|
||||
copy->_inWater = _inWater;
|
||||
copy->_onFloor = _onFloor;
|
||||
copy->_jumpNext = _jumpNext;
|
||||
copy->_move = _move;
|
||||
copy->_strafe = _strafe;
|
||||
copy->_k_left = _k_left;
|
||||
copy->_k_right = _k_right;
|
||||
copy->_k_up = _k_up;
|
||||
copy->_k_down = _k_down;
|
||||
copy->_timeinair = _timeinair;
|
||||
copy->_timeInAir = _timeInAir;
|
||||
copy->_radius = _radius;
|
||||
copy->_eyeheight = _eyeheight;
|
||||
copy->_aboveeye = _aboveeye;
|
||||
copy->_lastupdate = _lastupdate;
|
||||
copy->_plag = _plag;
|
||||
copy->_eyeHeight = _eyeHeight;
|
||||
copy->_aboveEye = _aboveEye;
|
||||
copy->_lastUpdate = _lastUpdate;
|
||||
copy->_lag = _lag;
|
||||
copy->_ping = _ping;
|
||||
copy->_lifesequence = _lifesequence;
|
||||
copy->_lifeSequence = _lifeSequence;
|
||||
copy->_state = _state;
|
||||
copy->_frags = _frags;
|
||||
copy->_health = _health;
|
||||
copy->_armour = _armour;
|
||||
copy->_armourtype = _armourtype;
|
||||
copy->_quadmillis = _quadmillis;
|
||||
copy->_gunselect = _gunselect;
|
||||
copy->_gunwait = _gunwait;
|
||||
copy->_lastaction = _lastaction;
|
||||
copy->_lastattackgun = _lastattackgun;
|
||||
copy->_lastmove = _lastmove;
|
||||
copy->_armourType = _armourType;
|
||||
copy->_quadMillis = _quadMillis;
|
||||
copy->_gunSelect = _gunSelect;
|
||||
copy->_gunWait = _gunWait;
|
||||
copy->_lastAction = _lastAction;
|
||||
copy->_lastAttackGun = _lastAttackGun;
|
||||
copy->_lastMove = _lastMove;
|
||||
copy->_attacking = _attacking;
|
||||
|
||||
for (size_t i = 0; i < NUMGUNS; i++)
|
||||
copy->_ammo[i] = _ammo[i];
|
||||
|
||||
copy->_monsterstate = _monsterstate;
|
||||
copy->_mtype = _mtype;
|
||||
copy->_monsterState = _monsterState;
|
||||
copy->_monsterType = _monsterType;
|
||||
copy->_enemy = _enemy;
|
||||
copy->_targetyaw = _targetyaw;
|
||||
copy->_targetYaw = _targetYaw;
|
||||
copy->_blocked = _blocked;
|
||||
copy->_moving = _moving;
|
||||
copy->_trigger = _trigger;
|
||||
copy->_attacktarget = _attacktarget;
|
||||
copy->_attackTarget = _attackTarget;
|
||||
copy->_anger = _anger;
|
||||
|
||||
copy->_name = [_name copy];
|
||||
|
@ -117,49 +133,49 @@ struct dynent {
|
|||
{
|
||||
// This is frighteningly *TERRIBLE*, but the format used by existing
|
||||
// savegames.
|
||||
struct dynent data = { .o = _o,
|
||||
.vel = _vel,
|
||||
struct dynent data = { .origin = _origin,
|
||||
.velocity = _velocity,
|
||||
.yaw = _yaw,
|
||||
.pitch = _pitch,
|
||||
.roll = _roll,
|
||||
.maxspeed = _maxspeed,
|
||||
.outsidemap = _outsidemap,
|
||||
.inwater = _inwater,
|
||||
.onfloor = _onfloor,
|
||||
.jumpnext = _jumpnext,
|
||||
.maxSpeed = _maxSpeed,
|
||||
.outsideMap = _outsideMap,
|
||||
.inWater = _inWater,
|
||||
.onFloor = _onFloor,
|
||||
.jumpNext = _jumpNext,
|
||||
.move = _move,
|
||||
.strafe = _strafe,
|
||||
.k_left = _k_left,
|
||||
.k_right = _k_right,
|
||||
.k_up = _k_up,
|
||||
.k_down = _k_down,
|
||||
.timeinair = _timeinair,
|
||||
.timeInAir = _timeInAir,
|
||||
.radius = _radius,
|
||||
.eyeheight = _eyeheight,
|
||||
.aboveeye = _aboveeye,
|
||||
.lastupdate = _lastupdate,
|
||||
.plag = _plag,
|
||||
.eyeHeight = _eyeHeight,
|
||||
.aboveEye = _aboveEye,
|
||||
.lastUpdate = _lastUpdate,
|
||||
.lag = _lag,
|
||||
.ping = _ping,
|
||||
.lifesequence = _lifesequence,
|
||||
.lifeSequence = _lifeSequence,
|
||||
.state = _state,
|
||||
.frags = _frags,
|
||||
.health = _health,
|
||||
.armour = _armour,
|
||||
.armourtype = _armourtype,
|
||||
.quadmillis = _quadmillis,
|
||||
.gunselect = _gunselect,
|
||||
.gunwait = _gunwait,
|
||||
.lastaction = _lastaction,
|
||||
.lastattackgun = _lastattackgun,
|
||||
.lastmove = _lastmove,
|
||||
.armourType = _armourType,
|
||||
.quadMillis = _quadMillis,
|
||||
.gunSelect = _gunSelect,
|
||||
.gunWait = _gunWait,
|
||||
.lastAction = _lastAction,
|
||||
.lastAttackGun = _lastAttackGun,
|
||||
.lastMove = _lastMove,
|
||||
.attacking = _attacking,
|
||||
.monsterstate = _monsterstate,
|
||||
.mtype = _mtype,
|
||||
.targetyaw = _targetyaw,
|
||||
.monsterState = _monsterState,
|
||||
.monsterType = _monsterType,
|
||||
.targetYaw = _targetYaw,
|
||||
.blocked = _blocked,
|
||||
.moving = _moving,
|
||||
.trigger = _trigger,
|
||||
.attacktarget = _attacktarget,
|
||||
.attackTarget = _attackTarget,
|
||||
.anger = _anger };
|
||||
|
||||
for (int i = 0; i < NUMGUNS; i++)
|
||||
|
@ -180,56 +196,130 @@ struct dynent {
|
|||
|
||||
memcpy(&d, data.items, data.count);
|
||||
|
||||
_o = d.o;
|
||||
_vel = d.vel;
|
||||
_origin = d.origin;
|
||||
_velocity = d.velocity;
|
||||
_yaw = d.yaw;
|
||||
_pitch = d.pitch;
|
||||
_roll = d.roll;
|
||||
_maxspeed = d.maxspeed;
|
||||
_outsidemap = d.outsidemap;
|
||||
_inwater = d.inwater;
|
||||
_onfloor = d.onfloor;
|
||||
_jumpnext = d.jumpnext;
|
||||
_maxSpeed = d.maxSpeed;
|
||||
_outsideMap = d.outsideMap;
|
||||
_inWater = d.inWater;
|
||||
_onFloor = d.onFloor;
|
||||
_jumpNext = d.jumpNext;
|
||||
_move = d.move;
|
||||
_strafe = d.strafe;
|
||||
_k_left = d.k_left;
|
||||
_k_right = d.k_right;
|
||||
_k_up = d.k_up;
|
||||
_k_down = d.k_down;
|
||||
_timeinair = d.timeinair;
|
||||
_timeInAir = d.timeInAir;
|
||||
_radius = d.radius;
|
||||
_eyeheight = d.eyeheight;
|
||||
_aboveeye = d.aboveeye;
|
||||
_lastupdate = d.lastupdate;
|
||||
_plag = d.plag;
|
||||
_eyeHeight = d.eyeHeight;
|
||||
_aboveEye = d.aboveEye;
|
||||
_lastUpdate = d.lastUpdate;
|
||||
_lag = d.lag;
|
||||
_ping = d.ping;
|
||||
_lifesequence = d.lifesequence;
|
||||
_lifeSequence = d.lifeSequence;
|
||||
_state = d.state;
|
||||
_frags = d.frags;
|
||||
_health = d.health;
|
||||
_armour = d.armour;
|
||||
_armourtype = d.armourtype;
|
||||
_quadmillis = d.quadmillis;
|
||||
_gunselect = d.gunselect;
|
||||
_gunwait = d.gunwait;
|
||||
_lastaction = d.lastaction;
|
||||
_lastattackgun = d.lastattackgun;
|
||||
_lastmove = d.lastmove;
|
||||
_armourType = d.armourType;
|
||||
_quadMillis = d.quadMillis;
|
||||
_gunSelect = d.gunSelect;
|
||||
_gunWait = d.gunWait;
|
||||
_lastAction = d.lastAction;
|
||||
_lastAttackGun = d.lastAttackGun;
|
||||
_lastMove = d.lastMove;
|
||||
_attacking = d.attacking;
|
||||
|
||||
for (int i = 0; i < NUMGUNS; i++)
|
||||
_ammo[i] = d.ammo[i];
|
||||
|
||||
_monsterstate = d.monsterstate;
|
||||
_mtype = d.mtype;
|
||||
_targetyaw = d.targetyaw;
|
||||
_monsterState = d.monsterState;
|
||||
_monsterType = d.monsterType;
|
||||
_targetYaw = d.targetYaw;
|
||||
_blocked = d.blocked;
|
||||
_moving = d.moving;
|
||||
_trigger = d.trigger;
|
||||
_attacktarget = d.attacktarget;
|
||||
_attackTarget = d.attackTarget;
|
||||
_anger = d.anger;
|
||||
|
||||
_name = [[OFString alloc] initWithUTF8String:d.name];
|
||||
_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
|
||||
|
|
|
@ -21,7 +21,7 @@ renderclient(
|
|||
{
|
||||
int n = 3;
|
||||
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;
|
||||
int basetime = -(tmp & 0xFFF);
|
||||
if (d.state == CS_DEAD) {
|
||||
|
@ -33,8 +33,8 @@ renderclient(
|
|||
n = (intptr_t)d % 3;
|
||||
r = range[n];
|
||||
}
|
||||
basetime = d.lastaction;
|
||||
int t = lastmillis - d.lastaction;
|
||||
basetime = d.lastAction;
|
||||
int t = lastmillis - d.lastAction;
|
||||
if (t < 0 || t > 20000)
|
||||
return;
|
||||
if (t > (r - 1) * 100) {
|
||||
|
@ -47,25 +47,25 @@ renderclient(
|
|||
if (mz < -1000)
|
||||
return;
|
||||
// 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;
|
||||
} else if (d.state == CS_EDITING) {
|
||||
n = 16;
|
||||
} else if (d.state == CS_LAGGED) {
|
||||
n = 17;
|
||||
} else if (d.monsterstate == M_ATTACKING) {
|
||||
} else if (d.monsterState == M_ATTACKING) {
|
||||
n = 8;
|
||||
} else if (d.monsterstate == M_PAIN) {
|
||||
} else if (d.monsterState == M_PAIN) {
|
||||
n = 10;
|
||||
} else if ((!d.move && !d.strafe) || !d.moving) {
|
||||
n = 12;
|
||||
} else if (!d.onfloor && d.timeinair > 100) {
|
||||
} else if (!d.onFloor && d.timeInAir > 100) {
|
||||
n = 18;
|
||||
} else {
|
||||
n = 14;
|
||||
speed = 1200 / d.maxspeed * scale;
|
||||
speed = 1200 / d.maxSpeed * scale;
|
||||
if (hellpig)
|
||||
speed = 300 / d.maxspeed;
|
||||
speed = 300 / d.maxSpeed;
|
||||
}
|
||||
if (hellpig) {
|
||||
n++;
|
||||
|
@ -73,8 +73,8 @@ renderclient(
|
|||
mz -= 1.9f;
|
||||
}
|
||||
rendermodel(mdlname, frame[n], range[n], 0, 1.5f,
|
||||
OFMakeVector3D(d.o.x, mz, d.o.y), d.yaw + 90, d.pitch / 2, team,
|
||||
scale, speed, 0, basetime);
|
||||
OFMakeVector3D(d.origin.x, mz, d.origin.y), d.yaw + 90, d.pitch / 2,
|
||||
team, scale, speed, 0, basetime);
|
||||
}
|
||||
|
||||
extern int democlientnum;
|
||||
|
@ -107,7 +107,7 @@ static OFMutableArray<OFString *> *scoreLines;
|
|||
void
|
||||
renderscore(DynamicEntity *d)
|
||||
{
|
||||
OFString *lag = [OFString stringWithFormat:@"%d", d.plag];
|
||||
OFString *lag = [OFString stringWithFormat:@"%d", d.lag];
|
||||
OFString *name = [OFString stringWithFormat:@"(%@)", d.name];
|
||||
OFString *line =
|
||||
[OFString stringWithFormat:@"%d\t%@\t%d\t%@\t%@", d.frags,
|
||||
|
|
143
src/clientgame.m
143
src/clientgame.m
|
@ -24,7 +24,7 @@ OFMutableArray *players; // other clients
|
|||
void
|
||||
initPlayers()
|
||||
{
|
||||
player1 = newdynent();
|
||||
player1 = [[DynamicEntity alloc] init];
|
||||
players = [[OFMutableArray alloc] init];
|
||||
}
|
||||
|
||||
|
@ -42,101 +42,6 @@ getclientmap()
|
|||
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
|
||||
respawnself()
|
||||
{
|
||||
|
@ -203,7 +108,7 @@ otherplayers()
|
|||
if (player == [OFNull null])
|
||||
return;
|
||||
|
||||
const int lagtime = lastmillis - [player lastupdate];
|
||||
const int lagtime = lastmillis - [player lastUpdate];
|
||||
if (lagtime > 1000 && [player state] == CS_ALIVE) {
|
||||
[player setState:CS_LAGGED];
|
||||
return;
|
||||
|
@ -271,11 +176,11 @@ updateworld(int millis) // main game update loop
|
|||
if (!demoplayback) {
|
||||
monsterthink();
|
||||
if (player1.state == CS_DEAD) {
|
||||
if (lastmillis - player1.lastaction < 2000) {
|
||||
if (lastmillis - player1.lastAction < 2000) {
|
||||
player1.move = player1.strafe = 0;
|
||||
moveplayer(player1, 10, false);
|
||||
} else if (!m_arena && !m_sp &&
|
||||
lastmillis - player1.lastaction > 10000)
|
||||
lastmillis - player1.lastAction > 10000)
|
||||
respawn();
|
||||
} else if (!intermission) {
|
||||
moveplayer(player1, 20, true);
|
||||
|
@ -296,14 +201,14 @@ entinmap(DynamicEntity *d)
|
|||
{
|
||||
float dx = (rnd(21) - 10) / 10.0f * i; // increasing distance
|
||||
float dy = (rnd(21) - 10) / 10.0f * i;
|
||||
OFVector3D old = d.o;
|
||||
d.o = OFMakeVector3D(d.o.x + dx, d.o.y + dy, d.o.z);
|
||||
OFVector3D old = d.origin;
|
||||
d.origin = OFAddVector3D(d.origin, OFMakeVector3D(dx, dy, 0));
|
||||
if (collide(d, true, 0, 0))
|
||||
return;
|
||||
d.o = old;
|
||||
d.origin = old;
|
||||
}
|
||||
conoutf(
|
||||
@"can't find entity spawn spot! (%d, %d)", (int)d.o.x, (int)d.o.y);
|
||||
conoutf(@"can't find entity spawn spot! (%d, %d)", (int)d.origin.x,
|
||||
(int)d.origin.y);
|
||||
// leave ent at original pos, possibly stuck
|
||||
}
|
||||
|
||||
|
@ -317,15 +222,16 @@ spawnplayer(DynamicEntity *d)
|
|||
int r = fixspawn-- > 0 ? 4 : rnd(10) + 1;
|
||||
loopi(r) spawncycle = findentity(PLAYERSTART, spawncycle + 1);
|
||||
if (spawncycle != -1) {
|
||||
d.o = OFMakeVector3D(
|
||||
d.origin = OFMakeVector3D(
|
||||
ents[spawncycle].x, ents[spawncycle].y, ents[spawncycle].z);
|
||||
d.yaw = ents[spawncycle].attr1;
|
||||
d.pitch = 0;
|
||||
d.roll = 0;
|
||||
} else
|
||||
d.o = OFMakeVector3D((float)ssize / 2, (float)ssize / 2, 4);
|
||||
d.origin =
|
||||
OFMakeVector3D((float)ssize / 2, (float)ssize / 2, 4);
|
||||
entinmap(d);
|
||||
spawnstate(d);
|
||||
[d resetToSpawnState];
|
||||
d.state = CS_ALIVE;
|
||||
}
|
||||
|
||||
|
@ -336,7 +242,7 @@ spawnplayer(DynamicEntity *d)
|
|||
{ \
|
||||
player1.s = isdown; \
|
||||
player1.v = isdown ? d : (player1.os ? -(d) : 0); \
|
||||
player1.lastmove = lastmillis; \
|
||||
player1.lastMove = lastmillis; \
|
||||
}
|
||||
|
||||
dir(backward, move, -1, k_down, k_up);
|
||||
|
@ -358,7 +264,7 @@ attack(bool on)
|
|||
void
|
||||
jumpn(bool on)
|
||||
{
|
||||
if (!intermission && (player1.jumpnext = on))
|
||||
if (!intermission && (player1.jumpNext = on))
|
||||
respawn();
|
||||
}
|
||||
|
||||
|
@ -406,7 +312,7 @@ selfdamage(int damage, int actor, DynamicEntity *act)
|
|||
damageblend(damage);
|
||||
demoblend(damage);
|
||||
// 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)
|
||||
ad = player1.armour;
|
||||
player1.armour -= ad;
|
||||
|
@ -440,14 +346,14 @@ selfdamage(int damage, int actor, DynamicEntity *act)
|
|||
}
|
||||
showscores(true);
|
||||
addmsg(1, 2, SV_DIED, actor);
|
||||
player1.lifesequence++;
|
||||
player1.lifeSequence++;
|
||||
player1.attacking = false;
|
||||
player1.state = CS_DEAD;
|
||||
player1.pitch = 0;
|
||||
player1.roll = 60;
|
||||
playsound(S_DIE1 + rnd(2), NULL);
|
||||
spawnstate(player1);
|
||||
player1.lastaction = lastmillis;
|
||||
[player1 resetToSpawnState];
|
||||
player1.lastAction = lastmillis;
|
||||
} else
|
||||
playsound(S_PAIN6, NULL);
|
||||
}
|
||||
|
@ -473,10 +379,17 @@ getclient(int cn) // ensure valid entity
|
|||
neterr(@"clientnum");
|
||||
return nil;
|
||||
}
|
||||
|
||||
while (cn >= players.count)
|
||||
[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
|
||||
|
|
|
@ -142,7 +142,7 @@ disconnect(bool onlyclean, bool async)
|
|||
disconnecting = 0;
|
||||
clientnum = -1;
|
||||
c2sinit = false;
|
||||
player1.lifesequence = 0;
|
||||
player1.lifeSequence = 0;
|
||||
[players removeAllObjects];
|
||||
|
||||
localdisconnect();
|
||||
|
@ -300,20 +300,20 @@ c2sinfo(DynamicEntity *d)
|
|||
putint(&p, clientnum);
|
||||
// quantize coordinates to 1/16th of a cube, between 1 and 3
|
||||
// bytes
|
||||
putint(&p, (int)(d.o.x * DMF));
|
||||
putint(&p, (int)(d.o.y * DMF));
|
||||
putint(&p, (int)(d.o.z * DMF));
|
||||
putint(&p, (int)(d.origin.x * DMF));
|
||||
putint(&p, (int)(d.origin.y * DMF));
|
||||
putint(&p, (int)(d.origin.z * DMF));
|
||||
putint(&p, (int)(d.yaw * DAF));
|
||||
putint(&p, (int)(d.pitch * DAF));
|
||||
putint(&p, (int)(d.roll * DAF));
|
||||
// quantize to 1/100, almost always 1 byte
|
||||
putint(&p, (int)(d.vel.x * DVF));
|
||||
putint(&p, (int)(d.vel.y * DVF));
|
||||
putint(&p, (int)(d.vel.z * DVF));
|
||||
// pack rest in 1 byte: strafe:2, move:2, onfloor:1, state:3
|
||||
putint(&p, (int)(d.velocity.x * DVF));
|
||||
putint(&p, (int)(d.velocity.y * DVF));
|
||||
putint(&p, (int)(d.velocity.z * DVF));
|
||||
// pack rest in 1 byte: strafe:2, move:2, onFloor:1, state:3
|
||||
putint(&p,
|
||||
(d.strafe & 3) | ((d.move & 3) << 2) |
|
||||
(((int)d.onfloor) << 4) |
|
||||
(((int)d.onFloor) << 4) |
|
||||
((editmode ? CS_EDITING : d.state) << 5));
|
||||
|
||||
if (senditemstoserver) {
|
||||
|
@ -339,7 +339,7 @@ c2sinfo(DynamicEntity *d)
|
|||
putint(&p, SV_INITC2S);
|
||||
sendstring(player1.name, &p);
|
||||
sendstring(player1.team, &p);
|
||||
putint(&p, player1.lifesequence);
|
||||
putint(&p, player1.lifeSequence);
|
||||
}
|
||||
for (OFData *msg in messages) {
|
||||
// send messages collected during the previous frames
|
||||
|
|
|
@ -38,26 +38,27 @@ void
|
|||
updatepos(DynamicEntity *d)
|
||||
{
|
||||
const float r = player1.radius + d.radius;
|
||||
const float dx = player1.o.x - d.o.x;
|
||||
const float dy = player1.o.y - d.o.y;
|
||||
const float dz = player1.o.z - d.o.z;
|
||||
const float rz = player1.aboveeye + d.eyeheight;
|
||||
const float dx = player1.origin.x - d.origin.x;
|
||||
const float dy = player1.origin.y - d.origin.y;
|
||||
const float dz = player1.origin.z - d.origin.z;
|
||||
const float rz = player1.aboveEye + d.eyeHeight;
|
||||
const float fx = (float)fabs(dx), fy = (float)fabs(dy),
|
||||
fz = (float)fabs(dz);
|
||||
if (fx < r && fy < r && fz < rz && d.state != CS_DEAD) {
|
||||
if (fx < fy)
|
||||
// push aside
|
||||
d.o = OFMakeVector3D(d.o.x,
|
||||
d.o.y + (dy < 0 ? r - fy : -(r - fy)), d.o.z);
|
||||
d.origin = OFAddVector3D(d.origin,
|
||||
OFMakeVector3D(
|
||||
0, (dy < 0 ? r - fy : -(r - fy)), 0));
|
||||
else
|
||||
d.o = OFMakeVector3D(
|
||||
d.o.x + (dx < 0 ? r - fx : -(r - fx)), d.o.y,
|
||||
d.o.z);
|
||||
d.origin = OFAddVector3D(d.origin,
|
||||
OFMakeVector3D(
|
||||
(dx < 0 ? r - fx : -(r - fx)), 0, 0));
|
||||
}
|
||||
int lagtime = lastmillis - d.lastupdate;
|
||||
int lagtime = lastmillis - d.lastUpdate;
|
||||
if (lagtime) {
|
||||
d.plag = (d.plag * 5 + lagtime) / 6;
|
||||
d.lastupdate = lastmillis;
|
||||
d.lag = (d.lag * 5 + lagtime) / 6;
|
||||
d.lastUpdate = lastmillis;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,22 +119,22 @@ localservertoclient(uchar *buf, int len)
|
|||
tmp.x = getint(&p) / DMF;
|
||||
tmp.y = getint(&p) / DMF;
|
||||
tmp.z = getint(&p) / DMF;
|
||||
d.o = tmp;
|
||||
d.origin = tmp;
|
||||
d.yaw = getint(&p) / DAF;
|
||||
d.pitch = getint(&p) / DAF;
|
||||
d.roll = getint(&p) / DAF;
|
||||
tmp.x = getint(&p) / DVF;
|
||||
tmp.y = getint(&p) / DVF;
|
||||
tmp.z = getint(&p) / DVF;
|
||||
d.vel = tmp;
|
||||
d.velocity = tmp;
|
||||
int f = getint(&p);
|
||||
d.strafe = (f & 3) == 3 ? -1 : f & 3;
|
||||
f >>= 2;
|
||||
d.move = (f & 3) == 3 ? -1 : f & 3;
|
||||
d.onfloor = (f >> 2) & 1;
|
||||
d.onFloor = (f >> 2) & 1;
|
||||
int state = f >> 3;
|
||||
if (state == CS_DEAD && d.state != CS_DEAD)
|
||||
d.lastaction = lastmillis;
|
||||
d.lastAction = lastmillis;
|
||||
d.state = state;
|
||||
if (!demoplayback)
|
||||
updatepos(d);
|
||||
|
@ -141,7 +142,7 @@ localservertoclient(uchar *buf, int len)
|
|||
}
|
||||
|
||||
case SV_SOUND: {
|
||||
OFVector3D loc = d.o;
|
||||
OFVector3D loc = d.origin;
|
||||
playsound(getint(&p), &loc);
|
||||
break;
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ localservertoclient(uchar *buf, int len)
|
|||
d.name = @(text);
|
||||
sgetstr();
|
||||
d.team = @(text);
|
||||
d.lifesequence = getint(&p);
|
||||
d.lifeSequence = getint(&p);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -230,10 +231,10 @@ localservertoclient(uchar *buf, int len)
|
|||
int damage = getint(&p);
|
||||
int ls = getint(&p);
|
||||
if (target == clientnum) {
|
||||
if (ls == player1.lifesequence)
|
||||
if (ls == player1.lifeSequence)
|
||||
selfdamage(damage, cn, d);
|
||||
} else {
|
||||
OFVector3D loc = getclient(target).o;
|
||||
OFVector3D loc = getclient(target).origin;
|
||||
playsound(S_PAIN1 + rnd(5), &loc);
|
||||
}
|
||||
break;
|
||||
|
@ -267,9 +268,9 @@ localservertoclient(uchar *buf, int len)
|
|||
a.name, d.name);
|
||||
}
|
||||
}
|
||||
OFVector3D loc = d.o;
|
||||
OFVector3D loc = d.origin;
|
||||
playsound(S_DIE1 + rnd(2), &loc);
|
||||
d.lifesequence++;
|
||||
d.lifeSequence++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
30
src/cube.h
30
src/cube.h
|
@ -281,32 +281,10 @@ extern bool demoplayback;
|
|||
|
||||
// simplistic vector ops
|
||||
#define dotprod(u, v) ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z)
|
||||
#define vmul(u, f) \
|
||||
{ \
|
||||
OFVector3D tmp_ = u; \
|
||||
float tmp2_ = f; \
|
||||
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 vmul(u, f) u = OFMultiplyVector3D(u, OFMakeVector3D(f, f, f))
|
||||
#define vdiv(u, f) u = OFDivideVector3D(u, OFMakeVector3D(f, f, f))
|
||||
#define vadd(u, v) u = OFAddVector3D(u, v)
|
||||
#define vsub(u, v) u = OFSubtractVector3D(u, v)
|
||||
#define vdist(d, v, e, s) \
|
||||
OFVector3D v = s; \
|
||||
vsub(v, e); \
|
||||
|
|
|
@ -169,8 +169,9 @@ cursorupdate() // called every frame from hud
|
|||
|
||||
// selected wall
|
||||
if (fabs(sheight(s, s, z) - z) > 1) {
|
||||
x += x > player1.o.x ? 0.5f : -0.5f; // find right wall cube
|
||||
y += y > player1.o.y ? 0.5f : -0.5f;
|
||||
// find right wall cube
|
||||
x += (x > player1.origin.x ? 0.5f : -0.5f);
|
||||
y += (y > player1.origin.y ? 0.5f : -0.5f);
|
||||
|
||||
cx = (int)x;
|
||||
cy = (int)y;
|
||||
|
@ -622,7 +623,7 @@ void
|
|||
newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4)
|
||||
{
|
||||
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],
|
||||
[a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]);
|
||||
}
|
||||
|
|
|
@ -171,16 +171,16 @@ realpickup(int n, DynamicEntity *d)
|
|||
|
||||
case I_GREENARMOUR:
|
||||
d.armour = radditem(n, d.armour);
|
||||
d.armourtype = A_GREEN;
|
||||
d.armourType = A_GREEN;
|
||||
break;
|
||||
|
||||
case I_YELLOWARMOUR:
|
||||
d.armour = radditem(n, d.armour);
|
||||
d.armourtype = A_YELLOW;
|
||||
d.armourType = A_YELLOW;
|
||||
break;
|
||||
|
||||
case I_QUAD:
|
||||
d.quadmillis = radditem(n, d.quadmillis);
|
||||
d.quadMillis = radditem(n, d.quadMillis);
|
||||
conoutf(@"you got the quad!");
|
||||
break;
|
||||
}
|
||||
|
@ -214,10 +214,11 @@ teleport(int n, DynamicEntity *d)
|
|||
if (beenhere < 0)
|
||||
beenhere = e;
|
||||
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.pitch = 0;
|
||||
d.vel = OFMakeVector3D(0, 0, 0);
|
||||
d.velocity = OFMakeVector3D(0, 0, 0);
|
||||
entinmap(d);
|
||||
playsoundc(S_TELEPORT);
|
||||
break;
|
||||
|
@ -257,7 +258,7 @@ pickup(int n, DynamicEntity *d)
|
|||
|
||||
case I_GREENARMOUR:
|
||||
// (100h/100g only absorbs 166 damage)
|
||||
if (d.armourtype == A_YELLOW && d.armour > 66)
|
||||
if (d.armourType == A_YELLOW && d.armour > 66)
|
||||
break;
|
||||
additem(n, d.armour, 20);
|
||||
break;
|
||||
|
@ -267,7 +268,7 @@ pickup(int n, DynamicEntity *d)
|
|||
break;
|
||||
|
||||
case I_QUAD:
|
||||
additem(n, d.quadmillis, 60);
|
||||
additem(n, d.quadMillis, 60);
|
||||
break;
|
||||
|
||||
case CARROT:
|
||||
|
@ -293,8 +294,9 @@ pickup(int n, DynamicEntity *d)
|
|||
lastjumppad = lastmillis;
|
||||
OFVector3D v = OFMakeVector3D((int)(char)ents[n].attr3 / 10.0f,
|
||||
(int)(char)ents[n].attr2 / 10.0f, ents[n].attr1 / 10.0f);
|
||||
player1.vel = OFMakeVector3D(player1.vel.x, player1.vel.y, 0);
|
||||
vadd(player1.vel, v);
|
||||
player1.velocity =
|
||||
OFMakeVector3D(player1.velocity.x, player1.velocity.y, 0);
|
||||
vadd(player1.velocity, v);
|
||||
playsoundc(S_JUMPPAD);
|
||||
break;
|
||||
}
|
||||
|
@ -318,8 +320,8 @@ checkitems()
|
|||
return;
|
||||
|
||||
OFVector3D v = OFMakeVector3D(
|
||||
e.x, e.y, (float)S(e.x, e.y)->floor + player1.eyeheight);
|
||||
vdist(dist, t, player1.o, v);
|
||||
e.x, e.y, (float)S(e.x, e.y)->floor + player1.eyeHeight);
|
||||
vdist(dist, t, player1.origin, v);
|
||||
|
||||
if (dist < (e.type == TELEPORT ? 4 : 2.5))
|
||||
pickup(i, player1);
|
||||
|
@ -329,8 +331,8 @@ checkitems()
|
|||
void
|
||||
checkquad(int time)
|
||||
{
|
||||
if (player1.quadmillis && (player1.quadmillis -= time) < 0) {
|
||||
player1.quadmillis = 0;
|
||||
if (player1.quadMillis && (player1.quadMillis -= time) < 0) {
|
||||
player1.quadMillis = 0;
|
||||
playsoundc(S_PUPOUT);
|
||||
conoutf(@"quad damage is over");
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "cube.h"
|
||||
|
||||
#import "Menu.h"
|
||||
|
||||
#import "DynamicEntity.h"
|
||||
#import "MenuItem.h"
|
||||
|
||||
static OFMutableArray<OFNumber *> *menuStack;
|
||||
|
@ -13,7 +15,7 @@ void
|
|||
menuset(int menu)
|
||||
{
|
||||
if ((vmenu = menu) >= 1)
|
||||
resetmovement(player1);
|
||||
[player1 resetMovement];
|
||||
if (vmenu == 1)
|
||||
menus[1].menusel = 0;
|
||||
}
|
||||
|
|
115
src/monster.m
115
src/monster.m
|
@ -62,22 +62,22 @@ basicmonster(int type, int yaw, int state, int trigger, int move)
|
|||
conoutf(@"warning: unknown monster in spawn: %d", type);
|
||||
type = 0;
|
||||
}
|
||||
DynamicEntity *m = newdynent();
|
||||
struct monstertype *t = &monstertypes[(m.mtype = type)];
|
||||
m.eyeheight = 2.0f;
|
||||
m.aboveeye = 1.9f;
|
||||
DynamicEntity *m = [DynamicEntity entity];
|
||||
struct monstertype *t = &monstertypes[(m.monsterType = type)];
|
||||
m.eyeHeight = 2.0f;
|
||||
m.aboveEye = 1.9f;
|
||||
m.radius *= t->bscale / 10.0f;
|
||||
m.eyeheight *= t->bscale / 10.0f;
|
||||
m.aboveeye *= t->bscale / 10.0f;
|
||||
m.monsterstate = state;
|
||||
m.eyeHeight *= t->bscale / 10.0f;
|
||||
m.aboveEye *= t->bscale / 10.0f;
|
||||
m.monsterState = state;
|
||||
if (state != M_SLEEP)
|
||||
spawnplayer(m);
|
||||
m.trigger = lastmillis + trigger;
|
||||
m.targetyaw = m.yaw = (float)yaw;
|
||||
m.targetYaw = m.yaw = (float)yaw;
|
||||
m.move = move;
|
||||
m.enemy = player1;
|
||||
m.gunselect = t->gun;
|
||||
m.maxspeed = (float)t->speed;
|
||||
m.gunSelect = t->gun;
|
||||
m.maxSpeed = (float)t->speed;
|
||||
m.health = t->health;
|
||||
m.armour = 0;
|
||||
loopi(NUMGUNS) m.ammo[i] = 10000;
|
||||
|
@ -129,7 +129,7 @@ monsterclear()
|
|||
|
||||
DynamicEntity *m =
|
||||
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);
|
||||
monstertotal++;
|
||||
}
|
||||
|
@ -176,9 +176,9 @@ los(float lx, float ly, float lz, float bx, float by, float bz, OFVector3D *v)
|
|||
bool
|
||||
enemylos(DynamicEntity *m, OFVector3D *v)
|
||||
{
|
||||
*v = m.o;
|
||||
return los(
|
||||
m.o.x, m.o.y, m.o.z, m.enemy.o.x, m.enemy.o.y, m.enemy.o.z, v);
|
||||
*v = m.origin;
|
||||
return los(m.origin.x, m.origin.y, m.origin.z, m.enemy.origin.x,
|
||||
m.enemy.origin.y, m.enemy.origin.z, v);
|
||||
}
|
||||
|
||||
// monster AI is sequenced using transitions: they are in a particular state
|
||||
|
@ -192,7 +192,7 @@ enemylos(DynamicEntity *m, OFVector3D *v)
|
|||
void
|
||||
transition(DynamicEntity *m, int state, int moving, int n, int r)
|
||||
{
|
||||
m.monsterstate = state;
|
||||
m.monsterState = state;
|
||||
m.move = moving;
|
||||
n = n * 130 / 100;
|
||||
m.trigger = lastmillis + n - skill * (n / 16) + rnd(r + 1);
|
||||
|
@ -215,41 +215,42 @@ monsteraction(DynamicEntity *m)
|
|||
m.enemy = player1;
|
||||
m.anger = 0;
|
||||
}
|
||||
normalise(m, m.targetyaw);
|
||||
normalise(m, m.targetYaw);
|
||||
// slowly turn monster towards his target
|
||||
if (m.targetyaw > m.yaw) {
|
||||
if (m.targetYaw > m.yaw) {
|
||||
m.yaw += curtime * 0.5f;
|
||||
if (m.targetyaw < m.yaw)
|
||||
m.yaw = m.targetyaw;
|
||||
if (m.targetYaw < m.yaw)
|
||||
m.yaw = m.targetYaw;
|
||||
} else {
|
||||
m.yaw -= curtime * 0.5f;
|
||||
if (m.targetyaw > m.yaw)
|
||||
m.yaw = m.targetyaw;
|
||||
if (m.targetYaw > m.yaw)
|
||||
m.yaw = m.targetYaw;
|
||||
}
|
||||
|
||||
vdist(disttoenemy, vectoenemy, m.o, m.enemy.o);
|
||||
m.pitch = atan2(m.enemy.o.z - m.o.z, disttoenemy) * 180 / PI;
|
||||
vdist(disttoenemy, vectoenemy, m.origin, m.enemy.origin);
|
||||
m.pitch = atan2(m.enemy.origin.z - m.origin.z, disttoenemy) * 180 / PI;
|
||||
|
||||
// special case: if we run into scenery
|
||||
if (m.blocked) {
|
||||
m.blocked = false;
|
||||
// try to jump over obstackle (rare)
|
||||
if (!rnd(20000 / monstertypes[m.mtype].speed))
|
||||
m.jumpnext = true;
|
||||
if (!rnd(20000 / monstertypes[m.monsterType].speed))
|
||||
m.jumpNext = true;
|
||||
// search for a way around (common)
|
||||
else if (m.trigger < lastmillis &&
|
||||
(m.monsterstate != M_HOME || !rnd(5))) {
|
||||
(m.monsterState != M_HOME || !rnd(5))) {
|
||||
// patented "random walk" AI pathfinding (tm) ;)
|
||||
m.targetyaw += 180 + rnd(180);
|
||||
m.targetYaw += 180 + rnd(180);
|
||||
transition(m, M_SEARCH, 1, 400, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
float enemyyaw =
|
||||
-(float)atan2(m.enemy.o.x - m.o.x, m.enemy.o.y - m.o.y) / PI * 180 +
|
||||
float enemyYaw = -(float)atan2(m.enemy.origin.x - m.origin.x,
|
||||
m.enemy.origin.y - m.origin.y) /
|
||||
PI * 180 +
|
||||
180;
|
||||
|
||||
switch (m.monsterstate) {
|
||||
switch (m.monsterState) {
|
||||
case M_PAIN:
|
||||
case M_ATTACKING:
|
||||
case M_SEARCH:
|
||||
|
@ -263,15 +264,15 @@ monsteraction(DynamicEntity *m)
|
|||
OFVector3D target;
|
||||
if (editmode || !enemylos(m, &target))
|
||||
return; // skip running physics
|
||||
normalise(m, enemyyaw);
|
||||
float angle = (float)fabs(enemyyaw - m.yaw);
|
||||
normalise(m, enemyYaw);
|
||||
float angle = (float)fabs(enemyYaw - m.yaw);
|
||||
if (disttoenemy < 8 // the better the angle to the player, the
|
||||
// further the monster can see/hear
|
||||
|| (disttoenemy < 16 && angle < 135) ||
|
||||
(disttoenemy < 32 && angle < 90) ||
|
||||
(disttoenemy < 64 && angle < 45) || angle < 10) {
|
||||
transition(m, M_HOME, 1, 500, 200);
|
||||
OFVector3D loc = m.o;
|
||||
OFVector3D loc = m.origin;
|
||||
playsound(S_GRUNT1 + rnd(2), &loc);
|
||||
}
|
||||
break;
|
||||
|
@ -281,10 +282,10 @@ monsteraction(DynamicEntity *m)
|
|||
// this state is the delay between wanting to shoot and actually
|
||||
// firing
|
||||
if (m.trigger < lastmillis) {
|
||||
m.lastaction = 0;
|
||||
m.lastAction = 0;
|
||||
m.attacking = true;
|
||||
OFVector3D attacktarget = m.attacktarget;
|
||||
shoot(m, &attacktarget);
|
||||
OFVector3D attackTarget = m.attackTarget;
|
||||
shoot(m, &attackTarget);
|
||||
transition(m, M_ATTACKING, 0, 600, 0);
|
||||
}
|
||||
break;
|
||||
|
@ -292,7 +293,7 @@ monsteraction(DynamicEntity *m)
|
|||
case M_HOME:
|
||||
// monster has visual contact, heads straight for player and
|
||||
// may want to shoot at any time
|
||||
m.targetyaw = enemyyaw;
|
||||
m.targetYaw = enemyYaw;
|
||||
if (m.trigger < lastmillis) {
|
||||
OFVector3D target;
|
||||
if (!enemylos(m, &target)) {
|
||||
|
@ -305,13 +306,15 @@ monsteraction(DynamicEntity *m)
|
|||
if (!rnd((int)disttoenemy / 3 + 1) &&
|
||||
m.enemy.state == CS_ALIVE) {
|
||||
// get ready to fire
|
||||
m.attacktarget = target;
|
||||
m.attackTarget = target;
|
||||
transition(m, M_AIMING, 0,
|
||||
monstertypes[m.mtype].lag, 10);
|
||||
monstertypes[m.monsterType].lag,
|
||||
10);
|
||||
} else
|
||||
// track player some more
|
||||
transition(m, M_HOME, 1,
|
||||
monstertypes[m.mtype].rate, 0);
|
||||
monstertypes[m.monsterType].rate,
|
||||
0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -324,13 +327,14 @@ void
|
|||
monsterpain(DynamicEntity *m, int damage, DynamicEntity *d)
|
||||
{
|
||||
// a monster hit us
|
||||
if (d.monsterstate) {
|
||||
if (d.monsterState) {
|
||||
// guard for RL guys shooting themselves :)
|
||||
if (m != d) {
|
||||
// don't attack straight away, first get angry
|
||||
m.anger++;
|
||||
int anger = m.mtype == d.mtype ? m.anger / 2 : m.anger;
|
||||
if (anger >= monstertypes[m.mtype].loyalty)
|
||||
int anger = m.monsterType == d.monsterType ? m.anger / 2
|
||||
: m.anger;
|
||||
if (anger >= monstertypes[m.monsterType].loyalty)
|
||||
// monster infight if very angry
|
||||
m.enemy = d;
|
||||
}
|
||||
|
@ -340,20 +344,20 @@ monsterpain(DynamicEntity *m, int damage, DynamicEntity *d)
|
|||
m.enemy = d;
|
||||
}
|
||||
// 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) {
|
||||
m.state = CS_DEAD;
|
||||
m.lastaction = lastmillis;
|
||||
m.lastAction = lastmillis;
|
||||
numkilled++;
|
||||
player1.frags = numkilled;
|
||||
OFVector3D loc = m.o;
|
||||
playsound(monstertypes[m.mtype].diesound, &loc);
|
||||
OFVector3D loc = m.origin;
|
||||
playsound(monstertypes[m.monsterType].diesound, &loc);
|
||||
int remain = monstertotal - numkilled;
|
||||
if (remain > 0 && remain <= 5)
|
||||
conoutf(@"only %d monster(s) remaining", remain);
|
||||
} else {
|
||||
OFVector3D loc = m.o;
|
||||
playsound(monstertypes[m.mtype].painsound, &loc);
|
||||
OFVector3D loc = m.origin;
|
||||
playsound(monstertypes[m.monsterType].painsound, &loc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,14 +397,14 @@ monsterthink()
|
|||
OFMakeVector3D(e.x, e.y, (float)S(e.x, e.y)->floor);
|
||||
for (DynamicEntity *monster in monsters) {
|
||||
if (monster.state == CS_DEAD) {
|
||||
if (lastmillis - monster.lastaction < 2000) {
|
||||
if (lastmillis - monster.lastAction < 2000) {
|
||||
monster.move = 0;
|
||||
moveplayer(monster, 1, false);
|
||||
}
|
||||
} else {
|
||||
v.z += monster.eyeheight;
|
||||
vdist(dist, t, monster.o, v);
|
||||
v.z -= monster.eyeheight;
|
||||
v.z += monster.eyeHeight;
|
||||
vdist(dist, t, monster.origin, v);
|
||||
v.z -= monster.eyeHeight;
|
||||
|
||||
if (dist < 4)
|
||||
teleport(i, monster);
|
||||
|
@ -418,6 +422,7 @@ monsterrender()
|
|||
{
|
||||
for (DynamicEntity *monster in monsters)
|
||||
renderclient(monster, false,
|
||||
monstertypes[monster.mtype].mdlname, monster.mtype == 5,
|
||||
monstertypes[monster.mtype].mscale / 10.0f);
|
||||
monstertypes[monster.monsterType].mdlname,
|
||||
monster.monsterType == 5,
|
||||
monstertypes[monster.monsterType].mscale / 10.0f);
|
||||
}
|
||||
|
|
186
src/physics.m
186
src/physics.m
|
@ -17,22 +17,26 @@ plcollide(
|
|||
{
|
||||
if (o.state != CS_ALIVE)
|
||||
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;
|
||||
if (d.monsterstate)
|
||||
if (d.monsterState)
|
||||
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)
|
||||
*headspace = 10;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -69,11 +73,11 @@ mmcollide(DynamicEntity *d, float *hi, float *lo)
|
|||
continue;
|
||||
|
||||
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)(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)
|
||||
*hi = mmz;
|
||||
} else if (mmz + mmi.h > *lo)
|
||||
|
@ -91,21 +95,21 @@ bool
|
|||
collide(DynamicEntity *d, bool spawn, float drop, float rise)
|
||||
{
|
||||
// figure out integer cube rectangle this entity covers in map
|
||||
const float fx1 = d.o.x - d.radius;
|
||||
const float fy1 = d.o.y - d.radius;
|
||||
const float fx2 = d.o.x + d.radius;
|
||||
const float fy2 = d.o.y + d.radius;
|
||||
const float fx1 = d.origin.x - d.radius;
|
||||
const float fy1 = d.origin.y - d.radius;
|
||||
const float fx2 = d.origin.x + d.radius;
|
||||
const float fy2 = d.origin.y + d.radius;
|
||||
const int x1 = fast_f2nat(fx1);
|
||||
const int y1 = fast_f2nat(fy1);
|
||||
const int x2 = fast_f2nat(fx2);
|
||||
const int y2 = fast_f2nat(fy2);
|
||||
float hi = 127, lo = -128;
|
||||
// big monsters are afraid of heights, unless angry :)
|
||||
float minfloor = (d.monsterstate && !spawn && d.health > 100)
|
||||
? d.o.z - d.eyeheight - 4.5f
|
||||
float minfloor = (d.monsterState && !spawn && d.health > 100)
|
||||
? d.origin.z - d.eyeHeight - 4.5f
|
||||
: -1000.0f;
|
||||
|
||||
for (int x = x1; x <= x2; x++)
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
// collide with map
|
||||
if (OUTBORD(x, y))
|
||||
|
@ -160,8 +164,9 @@ collide(DynamicEntity *d, bool spawn, float drop, float rise)
|
|||
if (floor < minfloor)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hi - lo < d.eyeheight + d.aboveeye)
|
||||
if (hi - lo < d.eyeHeight + d.aboveEye)
|
||||
return false;
|
||||
|
||||
float headspace = 10;
|
||||
|
@ -171,53 +176,61 @@ collide(DynamicEntity *d, bool spawn, float drop, float rise)
|
|||
if (!plcollide(d, player, &headspace, &hi, &lo))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d != player1)
|
||||
if (!plcollide(d, player1, &headspace, &hi, &lo))
|
||||
return false;
|
||||
|
||||
// this loop can be a performance bottleneck with many monster on a slow
|
||||
// cpu, should replace with a blockmap but seems mostly fast enough
|
||||
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))
|
||||
return false;
|
||||
|
||||
headspace -= 0.01f;
|
||||
|
||||
mmcollide(d, &hi, &lo); // collide with map models
|
||||
|
||||
if (spawn) {
|
||||
// just drop to floor (sideeffect)
|
||||
d.o = OFMakeVector3D(d.o.x, d.o.y, lo + d.eyeheight);
|
||||
d.onfloor = true;
|
||||
d.origin =
|
||||
OFMakeVector3D(d.origin.x, d.origin.y, lo + d.eyeHeight);
|
||||
d.onFloor = true;
|
||||
} 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.01)
|
||||
// stick on step
|
||||
d.o = OFMakeVector3D(
|
||||
d.o.x, d.o.y, lo + d.eyeheight);
|
||||
d.origin = OFMakeVector3D(
|
||||
d.origin.x, d.origin.y, lo + d.eyeHeight);
|
||||
else if (space > -1.26f)
|
||||
// rise thru stair
|
||||
d.o =
|
||||
OFMakeVector3D(d.o.x, d.o.y, d.o.z + rise);
|
||||
d.origin = OFAddVector3D(
|
||||
d.origin, OFMakeVector3D(0, 0, rise));
|
||||
else
|
||||
return false;
|
||||
} else
|
||||
// gravity
|
||||
d.o = OFMakeVector3D(d.o.x, d.o.y,
|
||||
d.o.z - min(min(drop, space), headspace));
|
||||
d.origin = OFSubtractVector3D(d.origin,
|
||||
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.1)
|
||||
return false; // hack alert!
|
||||
// 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
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -251,7 +264,7 @@ physicsframe() // optimally schedule physics frames inside the graphics frames
|
|||
static void
|
||||
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;
|
||||
|
||||
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.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 =
|
||||
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;
|
||||
|
||||
// slowly apply friction and direction to
|
||||
// velocity, gives a smooth movement
|
||||
vmul(pl.vel, fpsfric - 1);
|
||||
vadd(pl.vel, d);
|
||||
vdiv(pl.vel, fpsfric);
|
||||
d = pl.vel;
|
||||
vmul(pl.velocity, fpsfric - 1);
|
||||
vadd(pl.velocity, d);
|
||||
vdiv(pl.velocity, fpsfric);
|
||||
d = pl.velocity;
|
||||
vmul(d, speed); // d is now frametime based velocity vector
|
||||
|
||||
pl.blocked = false;
|
||||
|
@ -288,52 +301,55 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
|
|||
|
||||
if (floating) {
|
||||
// just apply velocity
|
||||
vadd(pl.o, d);
|
||||
if (pl.jumpnext) {
|
||||
pl.jumpnext = false;
|
||||
pl.vel = OFMakeVector3D(pl.vel.x, pl.vel.y, 2);
|
||||
vadd(pl.origin, d);
|
||||
if (pl.jumpNext) {
|
||||
pl.jumpNext = false;
|
||||
pl.velocity =
|
||||
OFMakeVector3D(pl.velocity.x, pl.velocity.y, 2);
|
||||
}
|
||||
} else {
|
||||
// apply velocity with collision
|
||||
if (pl.onfloor || water) {
|
||||
if (pl.jumpnext) {
|
||||
pl.jumpnext = false;
|
||||
if (pl.onFloor || water) {
|
||||
if (pl.jumpNext) {
|
||||
pl.jumpNext = false;
|
||||
// physics impulse upwards
|
||||
pl.vel =
|
||||
OFMakeVector3D(pl.vel.x, pl.vel.y, 1.7);
|
||||
pl.velocity = OFMakeVector3D(
|
||||
pl.velocity.x, pl.velocity.y, 1.7);
|
||||
// dampen velocity change even harder, gives
|
||||
// correct water feel
|
||||
if (water)
|
||||
pl.vel = OFMakeVector3D(pl.vel.x / 8,
|
||||
pl.vel.y / 8, pl.vel.z);
|
||||
pl.velocity = OFMakeVector3D(
|
||||
pl.velocity.x / 8,
|
||||
pl.velocity.y / 8, pl.velocity.z);
|
||||
if (local)
|
||||
playsoundc(S_JUMP);
|
||||
else if (pl.monsterstate) {
|
||||
OFVector3D loc = pl.o;
|
||||
else if (pl.monsterState) {
|
||||
OFVector3D loc = pl.origin;
|
||||
playsound(S_JUMP, &loc);
|
||||
}
|
||||
} else if (pl.timeinair > 800) {
|
||||
} else if (pl.timeInAir > 800) {
|
||||
// if we land after long time must have been a
|
||||
// high jump, make thud sound
|
||||
if (local)
|
||||
playsoundc(S_LAND);
|
||||
else if (pl.monsterstate) {
|
||||
OFVector3D loc = pl.o;
|
||||
else if (pl.monsterState) {
|
||||
OFVector3D loc = pl.origin;
|
||||
playsound(S_LAND, &loc);
|
||||
}
|
||||
}
|
||||
pl.timeinair = 0;
|
||||
|
||||
pl.timeInAir = 0;
|
||||
} else
|
||||
pl.timeinair += curtime;
|
||||
pl.timeInAir += curtime;
|
||||
|
||||
const float gravity = 20;
|
||||
const float f = 1.0f / moveres;
|
||||
// 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
|
||||
if (water) {
|
||||
dropf = 5;
|
||||
pl.timeinair = 0;
|
||||
pl.timeInAir = 0;
|
||||
}
|
||||
// at high fps, gravity kicks in too fast
|
||||
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
|
||||
{
|
||||
// try move forward
|
||||
pl.o = OFMakeVector3D(pl.o.x + f * d.x,
|
||||
pl.o.y + f * d.y, pl.o.z + f * d.z);
|
||||
pl.origin = OFAddVector3D(pl.origin,
|
||||
OFMakeVector3D(f * d.x, f * d.y, f * d.z));
|
||||
if (collide(pl, false, drop, rise))
|
||||
continue;
|
||||
|
||||
// player stuck, try slide along y axis
|
||||
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)) {
|
||||
d.x = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// still stuck, try x axis
|
||||
pl.o = OFMakeVector3D(
|
||||
pl.o.x + f * d.x, pl.o.y - f * d.y, pl.o.z);
|
||||
pl.origin = OFAddVector3D(
|
||||
pl.origin, OFMakeVector3D(f * d.x, -f * d.y, 0));
|
||||
if (collide(pl, false, drop, rise)) {
|
||||
d.y = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// try just dropping down
|
||||
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)) {
|
||||
d.y = d.x = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -376,13 +399,16 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
|
|||
// detect wether player is outside map, used for skipping zbuffer clear
|
||||
// mostly
|
||||
|
||||
if (pl.o.x < 0 || pl.o.x >= ssize || pl.o.y < 0 || pl.o.y > ssize)
|
||||
pl.outsidemap = true;
|
||||
if (pl.origin.x < 0 || pl.origin.x >= ssize || pl.origin.y < 0 ||
|
||||
pl.origin.y > ssize)
|
||||
pl.outsideMap = true;
|
||||
else {
|
||||
struct sqr *s = S((int)pl.o.x, (int)pl.o.y);
|
||||
pl.outsidemap = SOLID(s) ||
|
||||
pl.o.z < s->floor - (s->type == FHF ? s->vdelta / 4 : 0) ||
|
||||
pl.o.z > s->ceil + (s->type == CHF ? s->vdelta / 4 : 0);
|
||||
struct sqr *s = S((int)pl.origin.x, (int)pl.origin.y);
|
||||
pl.outsideMap = SOLID(s) ||
|
||||
pl.origin.z <
|
||||
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
|
||||
|
@ -399,15 +425,15 @@ moveplayer4(DynamicEntity *pl, int moveres, bool local, int curtime)
|
|||
|
||||
// play sounds on water transitions
|
||||
|
||||
if (!pl.inwater && water) {
|
||||
OFVector3D loc = pl.o;
|
||||
if (!pl.inWater && water) {
|
||||
OFVector3D loc = pl.origin;
|
||||
playsound(S_SPLASH2, &loc);
|
||||
pl.vel = OFMakeVector3D(pl.vel.x, pl.vel.y, 0);
|
||||
} else if (pl.inwater && !water) {
|
||||
OFVector3D loc = pl.o;
|
||||
pl.velocity = OFMakeVector3D(pl.velocity.x, pl.velocity.y, 0);
|
||||
} else if (pl.inWater && !water) {
|
||||
OFVector3D loc = pl.origin;
|
||||
playsound(S_SPLASH1, &loc);
|
||||
}
|
||||
pl.inwater = water;
|
||||
pl.inWater = water;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -100,13 +100,11 @@ extern void changemap(OFString *name);
|
|||
extern void initclient();
|
||||
extern void spawnplayer(DynamicEntity *d);
|
||||
extern void selfdamage(int damage, int actor, DynamicEntity *act);
|
||||
extern DynamicEntity *newdynent();
|
||||
extern OFString *getclientmap();
|
||||
extern OFString *modestr(int n);
|
||||
extern DynamicEntity *getclient(int cn);
|
||||
extern void setclient(int cn, id client);
|
||||
extern void timeupdate(int timeremain);
|
||||
extern void resetmovement(DynamicEntity *d);
|
||||
extern void fixplayer1range();
|
||||
|
||||
// clientextras
|
||||
|
|
|
@ -335,7 +335,7 @@ gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
|
|||
readmatrices();
|
||||
if (editmode) {
|
||||
if (cursordepth == 1.0f)
|
||||
worldpos = player1.o;
|
||||
worldpos = player1.origin;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
cursorupdate();
|
||||
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);
|
||||
glColor3ub(255, 255, 255);
|
||||
if (crosshairfx) {
|
||||
if (player1.gunwait)
|
||||
if (player1.gunWait)
|
||||
glColor3ub(128, 128, 128);
|
||||
else if (player1.health <= 25)
|
||||
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);
|
||||
if (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();
|
||||
glPushMatrix();
|
||||
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);
|
||||
if (player1.armour)
|
||||
drawicon(
|
||||
(float)(player1.armourtype * 64), 0, 620, 1650);
|
||||
int g = player1.gunselect;
|
||||
(float)(player1.armourType * 64), 0, 620, 1650);
|
||||
int g = player1.gunSelect;
|
||||
int r = 64;
|
||||
if (g > 2) {
|
||||
g -= 3;
|
||||
|
|
|
@ -350,10 +350,10 @@ transplayer()
|
|||
glRotated(player1.pitch, -1.0, 0.0, 0.0);
|
||||
glRotated(player1.yaw, 0.0, 1.0, 0.0);
|
||||
|
||||
glTranslated(-player1.o.x,
|
||||
(player1.state == CS_DEAD ? player1.eyeheight - 0.2f : 0) -
|
||||
player1.o.z,
|
||||
-player1.o.y);
|
||||
glTranslated(-player1.origin.x,
|
||||
(player1.state == CS_DEAD ? player1.eyeHeight - 0.2f : 0) -
|
||||
player1.origin.z,
|
||||
-player1.origin.y);
|
||||
}
|
||||
|
||||
VARP(fov, 10, 105, 120);
|
||||
|
@ -371,15 +371,16 @@ OFString *hudgunnames[] = { @"hudguns/fist", @"hudguns/shotg",
|
|||
void
|
||||
drawhudmodel(int start, int end, float speed, int base)
|
||||
{
|
||||
rendermodel(hudgunnames[player1.gunselect], start, end, 0, 1.0f,
|
||||
OFMakeVector3D(player1.o.x, player1.o.z, player1.o.y),
|
||||
rendermodel(hudgunnames[player1.gunSelect], start, end, 0, 1.0f,
|
||||
OFMakeVector3D(
|
||||
player1.origin.x, player1.origin.z, player1.origin.y),
|
||||
player1.yaw + 90, player1.pitch, false, 1.0f, speed, 0, base);
|
||||
}
|
||||
|
||||
void
|
||||
drawhudgun(float fovy, float aspect, int farplane)
|
||||
{
|
||||
if (!hudgun /*|| !player1.gunselect*/)
|
||||
if (!hudgun /*|| !player1.gunSelect*/)
|
||||
return;
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
@ -390,10 +391,10 @@ drawhudgun(float fovy, float aspect, int farplane)
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
// glClear(GL_DEPTH_BUFFER_BIT);
|
||||
int rtime = reloadtime(player1.gunselect);
|
||||
if (player1.lastaction && player1.lastattackgun == player1.gunselect &&
|
||||
lastmillis - player1.lastaction < rtime) {
|
||||
drawhudmodel(7, 18, rtime / 18.0f, player1.lastaction);
|
||||
int rtime = reloadtime(player1.gunSelect);
|
||||
if (player1.lastAction && player1.lastAttackGun == player1.gunSelect &&
|
||||
lastmillis - player1.lastAction < rtime) {
|
||||
drawhudmodel(7, 18, rtime / 18.0f, player1.lastAction);
|
||||
} else
|
||||
drawhudmodel(6, 1, 100, 0);
|
||||
|
||||
|
@ -411,7 +412,7 @@ gl_drawframe(int w, int h, float curfps)
|
|||
float hf = hdr.waterlevel - 0.3f;
|
||||
float fovy = (float)fov * h / w;
|
||||
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_END, fog);
|
||||
|
@ -428,7 +429,7 @@ gl_drawframe(int w, int h, float curfps)
|
|||
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);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
|
@ -449,8 +450,8 @@ gl_drawframe(int w, int h, float curfps)
|
|||
curvert = 0;
|
||||
[strips removeAllItems];
|
||||
|
||||
render_world(player1.o.x, player1.o.y, player1.o.z, (int)player1.yaw,
|
||||
(int)player1.pitch, (float)fov, w, h);
|
||||
render_world(player1.origin.x, player1.origin.y, player1.origin.z,
|
||||
(int)player1.yaw, (int)player1.pitch, (float)fov, w, h);
|
||||
finishstrips();
|
||||
|
||||
gl_setupworld();
|
||||
|
|
|
@ -93,7 +93,7 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
|
|||
{
|
||||
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))
|
||||
return;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void
|
|||
render_particles(int time)
|
||||
{
|
||||
if (demoplayback && demotracking) {
|
||||
OFVector3D o = player1.o;
|
||||
OFVector3D o = player1.origin;
|
||||
OFVector3D nom = OFMakeVector3D(0, 0, 0);
|
||||
newparticle(&o, &nom, 100000000, 8);
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ loadgamerest()
|
|||
[data increaseCountBy:DynamicEntity.serializedSize];
|
||||
gzread(f, data.mutableItems, data.count);
|
||||
[player1 setFromSerializedData:data];
|
||||
player1.lastaction = lastmillis;
|
||||
player1.lastAction = lastmillis;
|
||||
|
||||
int nmonsters = gzgeti();
|
||||
OFArray<DynamicEntity *> *monsters = getmonsters();
|
||||
|
@ -237,9 +237,9 @@ loadgamerest()
|
|||
// lazy, could save id of enemy instead
|
||||
monster.enemy = player1;
|
||||
// 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)
|
||||
monster.lastaction = 0;
|
||||
monster.lastAction = 0;
|
||||
}
|
||||
restoremonsterstate();
|
||||
|
||||
|
@ -313,13 +313,13 @@ incomingdemodata(uchar *buf, int len, bool extras)
|
|||
gzwrite(f, buf, len);
|
||||
gzput(extras);
|
||||
if (extras) {
|
||||
gzput(player1.gunselect);
|
||||
gzput(player1.lastattackgun);
|
||||
gzputi(player1.lastaction - starttime);
|
||||
gzputi(player1.gunwait);
|
||||
gzput(player1.gunSelect);
|
||||
gzput(player1.lastAttackGun);
|
||||
gzputi(player1.lastAction - starttime);
|
||||
gzputi(player1.gunWait);
|
||||
gzputi(player1.health);
|
||||
gzputi(player1.armour);
|
||||
gzput(player1.armourtype);
|
||||
gzput(player1.armourType);
|
||||
loopi(NUMGUNS) gzput(player1.ammo[i]);
|
||||
gzput(player1.state);
|
||||
gzputi(bdamage);
|
||||
|
@ -440,16 +440,16 @@ demoplaybackstep()
|
|||
// read additional client side state not present in normal
|
||||
// network stream
|
||||
if ((extras = gzget())) {
|
||||
target.gunselect = gzget();
|
||||
target.lastattackgun = gzget();
|
||||
target.lastaction = scaletime(gzgeti());
|
||||
target.gunwait = gzgeti();
|
||||
target.gunSelect = gzget();
|
||||
target.lastAttackGun = gzget();
|
||||
target.lastAction = scaletime(gzgeti());
|
||||
target.gunWait = gzgeti();
|
||||
target.health = gzgeti();
|
||||
target.armour = gzgeti();
|
||||
target.armourtype = gzget();
|
||||
target.armourType = gzget();
|
||||
loopi(NUMGUNS) target.ammo[i] = gzget();
|
||||
target.state = gzget();
|
||||
target.lastmove = playbacktime;
|
||||
target.lastMove = playbacktime;
|
||||
if ((bdamage = gzgeti()))
|
||||
damageblend(bdamage);
|
||||
if ((ddamage = gzgeti())) {
|
||||
|
@ -462,9 +462,9 @@ demoplaybackstep()
|
|||
// insert latest copy of player into history
|
||||
if (extras &&
|
||||
(playerhistory.count == 0 ||
|
||||
playerhistory.lastObject.lastupdate != playbacktime)) {
|
||||
playerhistory.lastObject.lastUpdate != playbacktime)) {
|
||||
DynamicEntity *d = [target copy];
|
||||
d.lastupdate = playbacktime;
|
||||
d.lastUpdate = playbacktime;
|
||||
|
||||
if (playerhistory == nil)
|
||||
playerhistory = [[OFMutableArray alloc] init];
|
||||
|
@ -485,7 +485,7 @@ demoplaybackstep()
|
|||
// find 2 positions in history that surround interpolation time point
|
||||
size_t count = playerhistory.count;
|
||||
for (ssize_t i = count - 1; i >= 0; i--) {
|
||||
if (playerhistory[i].lastupdate < itime) {
|
||||
if (playerhistory[i].lastUpdate < itime) {
|
||||
DynamicEntity *a = playerhistory[i];
|
||||
DynamicEntity *b = a;
|
||||
|
||||
|
@ -503,16 +503,16 @@ demoplaybackstep()
|
|||
z = playerhistory[i - 1];
|
||||
// if(a==z || b==c)
|
||||
// printf("* %d\n", lastmillis);
|
||||
float bf = (itime - a.lastupdate) /
|
||||
(float)(b.lastupdate - a.lastupdate);
|
||||
float bf = (itime - a.lastUpdate) /
|
||||
(float)(b.lastUpdate - a.lastUpdate);
|
||||
fixwrap(a, player1);
|
||||
fixwrap(c, 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 (dist < 16) {
|
||||
catmulrom(
|
||||
z.o, a.o, b.o, c.o, bf, player1.o);
|
||||
catmulrom(z.origin, a.origin, b.origin,
|
||||
c.origin, bf, player1.origin);
|
||||
OFVector3D vz = OFMakeVector3D(
|
||||
z.yaw, z.pitch, z.roll);
|
||||
OFVector3D va = OFMakeVector3D(
|
||||
|
|
|
@ -117,7 +117,7 @@ updatechanvol(int chan, const OFVector3D *loc)
|
|||
{
|
||||
int vol = soundvol, pan = 255 / 2;
|
||||
if (loc) {
|
||||
vdist(dist, v, *loc, player1.o);
|
||||
vdist(dist, v, *loc, player1.origin);
|
||||
vol -= (int)(dist * 3 * soundvol /
|
||||
255); // simple mono distance attenuation
|
||||
if (stereo && (v.x != 0 || v.y != 0)) {
|
||||
|
|
93
src/weapon.m
93
src/weapon.m
|
@ -32,7 +32,7 @@ selectgun(int a, int b, int c)
|
|||
if (a < -1 || b < -1 || c < -1 || a >= NUMGUNS || b >= NUMGUNS ||
|
||||
c >= NUMGUNS)
|
||||
return;
|
||||
int s = player1.gunselect;
|
||||
int s = player1.gunSelect;
|
||||
if (a >= 0 && s != a && player1.ammo[a])
|
||||
s = a;
|
||||
else if (b >= 0 && s != b && player1.ammo[b])
|
||||
|
@ -49,9 +49,9 @@ selectgun(int a, int b, int c)
|
|||
s = GUN_RIFLE;
|
||||
else
|
||||
s = GUN_FIST;
|
||||
if (s != player1.gunselect)
|
||||
if (s != player1.gunSelect)
|
||||
playsoundc(S_WEAPLOAD);
|
||||
player1.gunselect = s;
|
||||
player1.gunSelect = s;
|
||||
// conoutf(@"%@ selected", (int)guns[s].name);
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ createrays(const OFVector3D *from, const OFVector3D *to)
|
|||
static bool
|
||||
intersect(DynamicEntity *d, const OFVector3D *from, const OFVector3D *to)
|
||||
{
|
||||
OFVector3D v = *to, w = d.o;
|
||||
OFVector3D v = *to, w = d.origin;
|
||||
const OFVector3D *p;
|
||||
vsub(v, *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 &&
|
||||
p->y <= d.o.y + d.radius && p->y >= d.o.y - d.radius &&
|
||||
p->z <= d.o.z + d.aboveeye && p->z >= d.o.z - d.eyeheight);
|
||||
return (p->x <= d.origin.x + d.radius &&
|
||||
p->x >= d.origin.x - d.radius && p->y <= d.origin.y + d.radius &&
|
||||
p->y >= d.origin.y - d.radius && p->z <= d.origin.z + d.aboveEye &&
|
||||
p->z >= d.origin.z - d.eyeHeight);
|
||||
}
|
||||
|
||||
OFString *
|
||||
|
@ -124,7 +125,7 @@ playerincrosshair()
|
|||
if (player == [OFNull null])
|
||||
continue;
|
||||
|
||||
OFVector3D o = player1.o;
|
||||
OFVector3D o = player1.origin;
|
||||
if (intersect(player, &o, &worldpos))
|
||||
return [player name];
|
||||
}
|
||||
|
@ -169,13 +170,13 @@ newprojectile(const OFVector3D *from, const OFVector3D *to, float speed,
|
|||
void
|
||||
hit(int target, int damage, DynamicEntity *d, DynamicEntity *at)
|
||||
{
|
||||
OFVector3D o = d.o;
|
||||
OFVector3D o = d.origin;
|
||||
if (d == player1)
|
||||
selfdamage(damage, at == player1 ? -1 : -2, at);
|
||||
else if (d.monsterstate)
|
||||
else if (d.monsterState)
|
||||
monsterpain(d, damage, at);
|
||||
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);
|
||||
}
|
||||
particle_splash(3, damage, 1000, &o);
|
||||
|
@ -191,7 +192,7 @@ radialeffect(
|
|||
{
|
||||
if (o.state != CS_ALIVE)
|
||||
return;
|
||||
vdist(dist, temp, *v, o.o);
|
||||
vdist(dist, temp, *v, o.origin);
|
||||
dist -= 2; // account for eye distance imprecision
|
||||
if (dist < RL_DAMRAD) {
|
||||
if (dist < 0)
|
||||
|
@ -199,7 +200,7 @@ radialeffect(
|
|||
int damage = (int)(qdam * (1 - (dist / RL_DAMRAD)));
|
||||
hit(cn, damage, o, at);
|
||||
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)
|
||||
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;
|
||||
|
@ -283,7 +284,7 @@ moveprojectiles(float time)
|
|||
projdamage(player1, p, &v, -1, -1, qdam);
|
||||
|
||||
for (DynamicEntity *monster in getmonsters())
|
||||
if (!vreject(monster.o, v, 10.0f) &&
|
||||
if (!vreject(monster.origin, v, 10.0f) &&
|
||||
monster != p.owner)
|
||||
projdamage(monster, p, &v, -1, i, qdam);
|
||||
}
|
||||
|
@ -312,7 +313,7 @@ void
|
|||
shootv(int gun, const OFVector3D *from, const OFVector3D *to, DynamicEntity *d,
|
||||
bool local)
|
||||
{
|
||||
OFVector3D loc = d.o;
|
||||
OFVector3D loc = d.origin;
|
||||
playsound(guns[gun].sound, d == player1 ? NULL : &loc);
|
||||
int pspeed = 25;
|
||||
switch (gun) {
|
||||
|
@ -334,7 +335,7 @@ shootv(int gun, const OFVector3D *from, const OFVector3D *to, DynamicEntity *d,
|
|||
case GUN_ICEBALL:
|
||||
case GUN_SLIMEBALL:
|
||||
pspeed = guns[gun].projspeed;
|
||||
if (d.monsterstate)
|
||||
if (d.monsterState)
|
||||
pspeed /= 2;
|
||||
newprojectile(from, to, (float)pspeed, local, d, gun);
|
||||
break;
|
||||
|
@ -353,7 +354,7 @@ hitpush(int target, int damage, DynamicEntity *d, DynamicEntity *at,
|
|||
hit(target, damage, d, at);
|
||||
vdist(dist, v, *from, *to);
|
||||
vmul(v, damage / dist / 50);
|
||||
vadd(d.vel, v);
|
||||
vadd(d.velocity, v);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -362,12 +363,12 @@ raydamage(DynamicEntity *o, const OFVector3D *from, const OFVector3D *to,
|
|||
{
|
||||
if (o.state != CS_ALIVE)
|
||||
return;
|
||||
int qdam = guns[d.gunselect].damage;
|
||||
if (d.quadmillis)
|
||||
int qdam = guns[d.gunSelect].damage;
|
||||
if (d.quadMillis)
|
||||
qdam *= 4;
|
||||
if (d.monsterstate)
|
||||
if (d.monsterState)
|
||||
qdam /= MONSTERDAMAGEFACTOR;
|
||||
if (d.gunselect == GUN_SG) {
|
||||
if (d.gunSelect == GUN_SG) {
|
||||
int damage = 0;
|
||||
loop(r, SGRAYS) if (intersect(o, from, &sg[r])) damage += qdam;
|
||||
if (damage)
|
||||
|
@ -379,52 +380,52 @@ raydamage(DynamicEntity *o, const OFVector3D *from, const OFVector3D *to,
|
|||
void
|
||||
shoot(DynamicEntity *d, const OFVector3D *targ)
|
||||
{
|
||||
int attacktime = lastmillis - d.lastaction;
|
||||
if (attacktime < d.gunwait)
|
||||
int attacktime = lastmillis - d.lastAction;
|
||||
if (attacktime < d.gunWait)
|
||||
return;
|
||||
d.gunwait = 0;
|
||||
d.gunWait = 0;
|
||||
if (!d.attacking)
|
||||
return;
|
||||
d.lastaction = lastmillis;
|
||||
d.lastattackgun = d.gunselect;
|
||||
if (!d.ammo[d.gunselect]) {
|
||||
d.lastAction = lastmillis;
|
||||
d.lastAttackGun = d.gunSelect;
|
||||
if (!d.ammo[d.gunSelect]) {
|
||||
playsoundc(S_NOAMMO);
|
||||
d.gunwait = 250;
|
||||
d.lastattackgun = -1;
|
||||
d.gunWait = 250;
|
||||
d.lastAttackGun = -1;
|
||||
return;
|
||||
}
|
||||
if (d.gunselect)
|
||||
d.ammo[d.gunselect]--;
|
||||
OFVector3D from = d.o;
|
||||
if (d.gunSelect)
|
||||
d.ammo[d.gunSelect]--;
|
||||
OFVector3D from = d.origin;
|
||||
OFVector3D to = *targ;
|
||||
from.z -= 0.2f; // below eye
|
||||
|
||||
vdist(dist, unitv, from, to);
|
||||
vdiv(unitv, dist);
|
||||
OFVector3D kickback = unitv;
|
||||
vmul(kickback, guns[d.gunselect].kickamount * -0.01f);
|
||||
vadd(d.vel, kickback);
|
||||
vmul(kickback, guns[d.gunSelect].kickamount * -0.01f);
|
||||
vadd(d.velocity, kickback);
|
||||
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
|
||||
to = from;
|
||||
vadd(to, unitv);
|
||||
}
|
||||
if (d.gunselect == GUN_SG)
|
||||
if (d.gunSelect == GUN_SG)
|
||||
createrays(&from, &to);
|
||||
|
||||
if (d.quadmillis && attacktime > 200)
|
||||
if (d.quadMillis && attacktime > 200)
|
||||
playsoundc(S_ITEMPUP);
|
||||
shootv(d.gunselect, &from, &to, d, true);
|
||||
if (!d.monsterstate)
|
||||
addmsg(1, 8, SV_SHOT, d.gunselect, (int)(from.x * DMF),
|
||||
shootv(d.gunSelect, &from, &to, d, true);
|
||||
if (!d.monsterState)
|
||||
addmsg(1, 8, SV_SHOT, d.gunSelect, (int)(from.x * DMF),
|
||||
(int)(from.y * DMF), (int)(from.z * DMF), (int)(to.x * 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;
|
||||
|
||||
[players enumerateObjectsUsingBlock:^(id player, size_t i, bool *stop) {
|
||||
|
@ -436,6 +437,6 @@ shoot(DynamicEntity *d, const OFVector3D *targ)
|
|||
if (monster != d)
|
||||
raydamage(monster, &from, &to, d, -2);
|
||||
|
||||
if (d.monsterstate)
|
||||
if (d.monsterState)
|
||||
raydamage(player1, &from, &to, d, -1);
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ closestent() // used for delent and edit mode ent display
|
|||
return;
|
||||
|
||||
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
|
||||
vdist(dist, t, player1.o, v);
|
||||
vdist(dist, t, player1.origin, v);
|
||||
if (dist < bdist) {
|
||||
best = i;
|
||||
bdist = dist;
|
||||
|
|
|
@ -205,7 +205,7 @@ dodynlight(const OFVector3D *vold, const OFVector3D *v, int reach, int strength,
|
|||
{
|
||||
if (!reach)
|
||||
reach = dynlight;
|
||||
if (owner.monsterstate)
|
||||
if (owner.monsterState)
|
||||
reach = reach / 2;
|
||||
if (!reach)
|
||||
return;
|
||||
|
|
|
@ -137,7 +137,7 @@ render_seg_new(
|
|||
// first collect occlusion information for this block
|
||||
for (int oy = y; oy < ys; oy++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue