r685 - in trunk: . base/gamedefs game
lordhavoc at icculus.org
lordhavoc at icculus.org
Mon Mar 27 04:16:28 EST 2006
Author: lordhavoc
Date: 2006-03-27 04:16:27 -0500 (Mon, 27 Mar 2006)
New Revision: 685
Added:
trunk/modelanim.c
trunk/modelanim.h
Modified:
trunk/Makefile
trunk/base/gamedefs/entities.csv
trunk/game/g_entity.c
trunk/game/g_entity.h
trunk/game/g_entityclass.c
trunk/game/g_main.c
trunk/game/g_main.h
trunk/game/g_network.c
trunk/game/g_packetbuffer.c
trunk/game/g_packetbuffer.h
trunk/game/g_render.c
trunk/game/g_world.c
trunk/mathlib.h
trunk/model.c
trunk/model.h
trunk/resource.c
trunk/resource.h
trunk/system.c
trunk/todo
Log:
some preparation work toward physics and animations
Modified: trunk/Makefile
===================================================================
--- trunk/Makefile 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/Makefile 2006-03-27 09:16:27 UTC (rev 685)
@@ -25,7 +25,7 @@
##### Common variables #####
GAMEOBJECTS= game/g_main.o game/g_render.o game/g_audio.o game/g_network.o game/g_packetbuffer.o game/g_util.o game/particle.o game/g_rain.o game/g_explosion.o game/g_commands.o game/g_entity.o game/g_entityclass.o game/g_world.o game/m_menucore.o
-ENGINEOBJECTS= polygon.o crc.o hash.o system.o console.o collision.o util.o nmemory.o nstring.o nfile.o matrixlib.o resource.o material.o model.o sound.o texture.o video.o dwmesh.o r_dyngl.o r_dynglstubs.o r_main.o fs/dir.o fs/dir_posix.o fs/fs.o fs/pak.o fs/zip.o fs/rw_ops.o s_main.o lhnet.o shell.o shell_lang.o cvar.o lhsound.o systemfallbacks.o
+ENGINEOBJECTS= polygon.o crc.o hash.o system.o console.o collision.o util.o nmemory.o nstring.o nfile.o matrixlib.o resource.o material.o model.o modelanim.o sound.o texture.o video.o dwmesh.o r_dyngl.o r_dynglstubs.o r_main.o fs/dir.o fs/dir_posix.o fs/fs.o fs/pak.o fs/zip.o fs/rw_ops.o s_main.o lhnet.o shell.o shell_lang.o cvar.o lhsound.o systemfallbacks.o
OBJECTS = $(GAMEOBJECTS) $(ENGINEOBJECTS)
CC=gcc
Modified: trunk/base/gamedefs/entities.csv
===================================================================
--- trunk/base/gamedefs/entities.csv 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/base/gamedefs/entities.csv 2006-03-27 09:16:27 UTC (rev 685)
@@ -1,56 +1,66 @@
-CodeName ParentCodeName EnglishName Class Model Mass Health Heal NoRemove I0Q I0R I0C I0A I0AR I0B I1Q I1R I1C I1A I1AR I1B I2Q I2R I2C I2A I2AR I2B I3Q I3R I3C I3A I3AR I3B I4Q I4R I4C I4A I4AR I4B I5Q I5R I5C I5A I5AR I5B I6Q I6R I6C I6A I6AR I6B I7Q I7R I7C I7A I7AR I7B I8Q I8R I8C I8A I8AR I8B I9Q I9R I9C I9A I9AR I9B AmmoMax AmmoRegen Projectile SemiRefire AutoRefire Physics StepHeight JumpVelocity Speed TopSpeed Acceleration Friction StopSpeed AirSpeed AirAcceleration AirFriction AirStopSpeed HoverThrust HoverAltitude Cloaking JumpFlight CrouchShield CrouchTurret LifeTime ImpactDelay FleshDamage ArmorDamage Force DamageRadius Shake ShakeRadius IdleAnim IdleFPS
-light Light light
-model Model model default
-model_sky Sky Model model_sky default
-room Room room
-infantry Infantry infantry infantry/infantry 90 200 10 1 weaponmachinegun 400 weapon 1 weaponpistol 60 pistol 1 weaponhandgrenade grenade1 1 weaponhandgrenade grenade2 1 weaponhandgrenade grenade3 infantry 0.3 4 5 10 2 10 20 0.02 0.1 0
-infscout Scout infantry infantry/scout 90 200 10 1 weaponplasmarifle 50 weapon 1 weaponpistol 60 pistol 1 weaponhandgrenade grenade1 1 weaponhandgrenade grenade2 1 weaponhandgrenade grenade3 infantry 0.3 4 5 10 2 10 20 0.02 0.1 0 TRUE
-infhellion Hellion infantry infantry/hellion 90 200 10 1 weaponmachinegun 400 weapon 1 weaponpistol 60 pistol 1 weaponhandgrenade grenade1 1 weaponhandgrenade grenade2 1 weaponhandgrenade grenade3 infantry 0.3 8 6 10 2 10 20 1 0.03 1 TRUE
-infmarauder Marauder infantry infantry/marauder 200 1000 40 1 weaponminigun 400 weapon 1 weaponpistol 60 pistol 1 weaponhandgrenade grenade1 1 weaponhandgrenade grenade2 1 weaponhandgrenade grenade3 1 weaponhandgrenade grenade4 1 weaponhandgrenade grenade5 infantry 0.3 6 5 10 2 10 20 0.2 0.03 0 TRUE
-infgranite Granite infantry infantry/granite 400 2000 80 1 weaponplasmacannon 30 10 weapon infantry 0.3 12 4 10 2 10 20 0.01 0.03 0 TRUE
-vehapc APC vehicle_apc vehicle/apc 3000 2000 50 weapon hover 0 0 0.2 1 20 0 0.01 5 20 0.5
-vehtankrailgun Railgun Hover Tank vehicle_tank vehicle/tankrailgun 3000 2000 50 1 weapontankrailgun 10 1 weapon hover 0 0 0.2 1 20 0 0.01 5 20 0.5
-vehdropship Drop Ship vehicle_dropship vehicle/dropship 2000 2000 50 weapon vtol 0 0 0.5 2 40 1 0.01 5
-turretrailgun Railgun Turret turret turret/turretrail 1000 3000 150 1 weaponturretrailgun 2 2 weapon default
-turretvulcan Vulcan Turret turret turret/turretvulcan 1000 3000 150 1 weaponturretvulcan 20 20 weapon default
-turretartillery Artillery Turret turret turret/turretartillery 1000 3000 150 1 weaponturretartillery 1 0.2 weapon default
-spawninfantry Infantry Spawn Pad spawnpad spawn/infantry 500 500 25 TRUE 1 1 infantry
-spawninfscout Scout Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 1 0.1 infscout
-spawninfhellion Hellion Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 1 0.1 infhellion
-spawninfmarauder Marauder Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 1 0.1 infmarauder
-spawninfgranite Granite Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 1 0.1 infgranite
-spawnvehapc APC Spawn Pad vehiclepad spawn/vehicle 10000 2000 100 TRUE 1 0.02 vehapc
-spawnvehtankrailgun Railgun Hover Tank Spawn Pad vehiclepad spawn/vehicle 10000 2000 100 TRUE 1 0.04 vehtankrailgun
-spawnvehdropship Drop Ship Spawn Pad vehiclepad spawn/vehicle 10000 2000 100 TRUE 1 0.02 vehdropship
-spawnturretrailgun Railgun Turret Spawn Pad vehiclepad spawn/turret 10000 2000 100 TRUE 1 0.02 turretrailgun
-spawnturretvulcan Vulcan Turret Spawn Pad vehiclepad spawn/turret 10000 2000 100 TRUE 1 0.02 turretvulcan
-spawnturretartillery Artillery Turret Spawn Pad vehiclepad spawn/turret 10000 2000 100 TRUE 1 0.02 turretartillery
-weaponhandgrenade Hand Grenade weapon weapon/handgrenade/body 0.2 1 projhandgrenade 0.5 0.5
-weaponpistol Pistol weapon weapon/pistol/body 1 60 projpistol 0.2 0.5
-weaponmachinegun Machinegun weapon weapon/machinegun/body 5 400 projmachinegun 0.06 0.13
-weaponminigun Minigun weapon weapon/minigun/body 20 1200 projminigun 0.05 0.05
-weaponsniperrifle Sniper Rifle weapon weapon/sniperrifle/body 4 25 projsniperrifle 0.5 1
-weaponrocketlauncher Rocket Launcher weapon weapon/rocketlauncher/body 10 20 projrocketlauncher 0.3 0.3
-weaponplasmacannon Plasma Cannon weapon weapon/plasmacannon/body 50 30 10 projplasmacannon 1 1
-weapontankrailgun Railgun weapon weapon/tankrailgun/body 50 10 2 projtankrailgun 1 1
-weaponturretrailgun Railgun weapon weapon/turretrailgun/body 50 2 1 projturretrailgun 1 1
-weaponturretvulcan Vulcan Cannon weapon weapon/turretvulcan/body 200 20 20 projturretvulcan 0.06 0.06
-weaponturretartillery Artillery Cannon weapon weapon/turretartillery/body 200 1 0.2 projturretartillery 5 5
-projhandgrenade Live Hand Grenade projectile weapon/handgrenade/projectile 0.2 default 10 3 4
-projpistol Pistol Bullet projectile weapon/pistol/projectile 0 default 1300 60 0
-projmachinegun Machinegun Bullet projectile weapon/machinegun/projectile 0 default 800 60 0
-projminigun Minigun Bullet projectile weapon/minigun/projectile 0 default 800 60 0
-projplasmacannon Plasma Cannon Ball projectile weapon/plasmacannon/projectile 0 default 10 0
-projtankrailgun Railgun Bolt projectile weapon/tankrailgun/projectile 0.5 default 60 0
-projturretrailgun Railgun Bolt projectile weapon/turretrailgun/projectile 0.1 default 60 0
-projturretvulcan Vulcan Turret Bullet projectile weapon/turretvulcan/projectile 0.01 default 60 0
-projturretartillery Artillery Cannon Shell projectile weapon/turretartillery/projectile 5 default 60 2
-expprojhandgrenade Hand Grenade Explosion explosion weapon/handgrenade/projectileexplosion 400 100 400 10 2 30
-expprojpistol Pistol Bullet Impact explosion weapon/pistol/projectileexplosion 50 30 0.1 0.01 0 0
-expprojmachinegun Machinegun Bullet Impact explosion weapon/machinegun/projectileexplosion 30 15 0.05 0.01 0 0
-expprojminigun Minigun Bullet Impact explosion weapon/minigun/projectileexplosion 30 15 0.05 0.01 0 0
-expprojplasmacannon Plasma Cannon Shell Explosion explosion weapon/plasmacannon/projectileexplosion 150 400 10 2 0 0
-expprojtankrailgun Railgun Bolt Impact explosion weapon/tankrailgun/projectileexplosion 200 900 50 0.5 1 10
-expprojturretrailgun Railgun Bolt Impact explosion weapon/turretrailgun/projectileexplosion 200 900 50 0.5 1 10
-expprojturretvulcan Vulcan Turret Bullet Impact explosion weapon/turretvulcan/projectileexplosion 20 30 1 0.01 0 0
-expprojturretartillery Artillery Cannon Shell Explosion explosion weapon/turretartillery/projectileexplosion 200 400 200 10 2 30
+CodeName ParentCodeName EnglishName Class Model Mass Health Heal NoRemove Respawn I0C I0B I1C I1B I2C I2B I3C I3B I4C I4B I5C I5B I6C I6B I7C I7B I8C I8B I9C I9B AmmoMax AmmoRegen Projectile Shots Spread SemiRefire AutoRefire Physics StepHeight JumpVelocity Speed TopSpeed Acceleration Friction StopSpeed AirSpeed AirAcceleration AirFriction AirStopSpeed HoverThrust HoverAltitude Cloaking JumpFlight CrouchShield CrouchTurret LifeTime ImpactDelay FleshDamage ArmorDamage Force DamageRadius Shake ShakeRadius IdleAnim IdleFPS
+light Light light
+model Model model default
+model_sky Sky Model model_sky default
+room Room room
+infantry Infantry infantry infantry/infantry 90 200 10 itemmachinegun weapon itempistol pistol itemhandgrenade grenade1 itemhandgrenade grenade2 itemhandgrenade grenade3 infantry 0.3 4 5 10 2 10 20 0.02 0.1 0
+infscout Scout infantry infantry/scout 90 200 10 itemsniperrifle weapon itempistol pistol itemhandgrenade grenade1 itemhandgrenade grenade2 itemhandgrenade grenade3 infantry 0.3 4 5 10 2 10 20 0.02 0.1 0 TRUE
+infhellion Hellion infantry infantry/hellion 90 200 10 itemmachinegun weapon itempistol pistol itemhandgrenade grenade1 itemhandgrenade grenade2 itemhandgrenade grenade3 infantry 0.3 8 6 10 2 10 20 1 0.03 1 TRUE
+infmarauder Marauder infantry infantry/marauder 200 1000 40 itemminigun weapon itempistol pistol itemhandgrenade grenade1 itemhandgrenade grenade2 itemhandgrenade grenade3 itemhandgrenade grenade4 itemhandgrenade grenade5 infantry 0.3 6 5 10 2 10 20 0.2 0.03 0 TRUE
+infgranite Granite infantry infantry/granite 400 2000 80 itemplasmacannon weapon infantry 0.3 12 4 10 2 10 20 0.01 0.03 0 TRUE
+vehapc APC vehicle_apc vehicle/apc 3000 2000 50 weapon hover 0 0 0.2 1 20 0 0.01 5 20 0.5
+vehtankrailgun Railgun Hover Tank vehicle_tank vehicle/tankrailgun 3000 2000 50 weapontankrailgun weapon hover 0 0 0.2 1 20 0 0.01 5 20 0.5
+vehdropship Drop Ship vehicle_dropship vehicle/dropship 2000 2000 50 weapon vtol 0 0 0.5 2 40 1 0.01 5
+turretrailgun Railgun Turret turret turret/turretrail 1000 3000 150 weaponturretrailgun weapon default
+turretvulcan Vulcan Turret turret turret/turretvulcan 1000 3000 150 weaponturretvulcan weapon default
+turretartillery Artillery Turret turret turret/turretartillery 1000 3000 150 weaponturretartillery weapon default
+spawninfantry Infantry Spawn Pad spawnpad spawn/infantry 500 500 25 TRUE 1 infantry spawn
+spawninfscout Scout Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 10 infscout spawn
+spawninfhellion Hellion Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 10 infhellion spawn
+spawninfmarauder Marauder Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 10 infmarauder spawn
+spawninfgranite Granite Spawn Pad spawnpad spawn/infantry 2000 1000 50 TRUE 10 infgranite spawn
+spawnvehapc APC Spawn Pad vehiclepad spawn/vehicle 10000 2000 100 TRUE 50 vehapc spawn
+spawnvehtankrailgun Railgun Hover Tank Spawn Pad vehiclepad spawn/vehicle 10000 2000 100 TRUE 50 vehtankrailgun spawn
+spawnvehdropship Drop Ship Spawn Pad vehiclepad spawn/vehicle 10000 2000 100 TRUE 50 vehdropship spawn
+spawnturretrailgun Railgun Turret Spawn Pad vehiclepad spawn/turret 10000 2000 100 TRUE 50 turretrailgun spawn
+spawnturretvulcan Vulcan Turret Spawn Pad vehiclepad spawn/turret 10000 2000 100 TRUE 50 turretvulcan spawn
+spawnturretartillery Artillery Turret Spawn Pad vehiclepad spawn/turret 10000 2000 100 TRUE 50 turretartillery spawn
+itemhandgrenade Hand Grenade item weapon/handgrenade/body 0.2 projhandgrenade 1 0.1 0.5 0.5
+itempistol Pistol item weapon/pistol/body 1 60 projpistol 1 0.01 0.2 0.5
+itemmachinegun Machinegun item weapon/machinegun/body 5 400 projmachinegun 1 0.01 0.06 0.13
+itemshotgun Flechette Shotgun item weapon/shotgun/body 5 50 projshotgun 8 0.03 0.2 0.5
+itemminigun Minigun item weapon/minigun/body 20 1200 projminigun 1 0.02 0.05 0.05
+itemsniperrifle Sniper Rifle item weapon/sniperrifle/body 4 25 projsniperrifle 1 0.0001 0.5 1
+itemgrenadelauncher Grenade Launcher item weapon/grenadelauncher/body 3 50 projgrenadelauncher 1 0.02 0.5 0.5
+itemrocketlauncher Rocket Launcher item weapon/rocketlauncher/body 10 20 projrocketlauncher 1 0.001 0.3 0.3
+itemplasmacannon Plasma Cannon item weapon/plasmacannon/body 50 30 10 projplasmacannon 1 0.01 1 1
+weapontankrailgun Railgun weapon weapon/tankrailgun/body 50 10 2 projtankrailgun 1 0.0001 1 1
+weaponturretrailgun Railgun weapon weapon/turretrailgun/body 50 2 1 projturretrailgun 1 0.01 1 1
+weaponturretvulcan Vulcan Cannon weapon weapon/turretvulcan/body 200 20 20 projturretvulcan 1 0.03 0.06 0.06
+weaponturretartillery Artillery Cannon weapon weapon/turretartillery/body 200 1 0.2 projturretartillery 1 0.01 5 5
+projhandgrenade Live Hand Grenade projectile weapon/handgrenade/projectile 0.2 default 10 1 0.1 3 4
+projpistol Pistol Bullet projectile weapon/pistol/projectile 0.01 default 1300 1 0.1 60 0
+projmachinegun Machinegun Bullet projectile weapon/machinegun/projectile 0.005 default 800 1 0.1 60 0
+projshotgun Shotgun Flechette projectile weapon/shotgun/projectile 0.02 default 1100 1 0.1 60 0
+projminigun Minigun Bullet projectile weapon/minigun/projectile 0.01 default 800 1 0.1 60 0
+projsniperrifle Sniper Rifle Flechette projectile weapon/sniperrifle/projectile 0.01 default 4000 1 0.1 60 0
+projgrenadelauncher Grenade Launcher Grenade projectile weapon/grenadelauncher/projectile 0.5 default 100 1 0.1 60 2
+projrocketlauncher Rocket Launcher Rocket projectile weapon/rocketlauncher/projectile 1 default 100 5000 1000 1 0.1 60 0
+projplasmacannon Plasma Cannon Ball projectile weapon/plasmacannon/projectile 0.005 default 400 1 0.1 10 0
+projtankrailgun Railgun Bolt projectile weapon/tankrailgun/projectile 0.5 default 4000 1 0.1 60 0
+projturretrailgun Railgun Bolt projectile weapon/turretrailgun/projectile 0.1 default 4000 1 0.1 60 0
+projturretvulcan Vulcan Turret Bullet projectile weapon/turretvulcan/projectile 0.01 default 1000 1 0.1 60 0
+projturretartillery Artillery Cannon Shell projectile weapon/turretartillery/projectile 5 default 300 1 0.01 60 2
+expprojhandgrenade Hand Grenade Explosion explosion weapon/handgrenade/projectileexplosion 400 100 400 10 2 30
+expprojpistol Pistol Bullet Impact explosion weapon/pistol/projectileexplosion 50 30 0.1 0.01 0 0
+expprojmachinegun Machinegun Bullet Impact explosion weapon/machinegun/projectileexplosion 30 15 0.05 0.01 0 0
+expprojshotgun Shotgun Flechette Impact explosion weapon/shotgun/projectileexplosion 20 20 0.05 0.01 0 0
+expprojminigun Minigun Bullet Impact explosion weapon/minigun/projectileexplosion 30 15 0.05 0.01 0 0
+expprojsniperrifle Sniper Rifle Flechette Impact explosion weapon/sniperrifle/projectileexplosion 150 150 0.05 0.01 0 0
+expprojgrenadelauncher Grenade Launcher Grenade Explosion explosion weapon/grenadelauncher/projectileexplosion 300 100 300 10 2 30
+expprojrocketlauncher Rocket Launcher Rocket Explosion explosion weapon/rocketlauncher/projectileexplosion 300 100 300 10 2 30
+expprojplasmacannon Plasma Cannon Shell Explosion explosion weapon/plasmacannon/projectileexplosion 150 400 10 2 0 0
+expprojtankrailgun Railgun Bolt Impact explosion weapon/tankrailgun/projectileexplosion 200 900 50 0.5 1 10
+expprojturretrailgun Railgun Bolt Impact explosion weapon/turretrailgun/projectileexplosion 200 900 50 0.5 1 10
+expprojturretvulcan Vulcan Turret Bullet Impact explosion weapon/turretvulcan/projectileexplosion 20 30 1 0.01 0 0
+expprojturretartillery Artillery Cannon Shell Explosion explosion weapon/turretartillery/projectileexplosion 200 400 200 10 2 30
Modified: trunk/game/g_entity.c
===================================================================
--- trunk/game/g_entity.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_entity.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -5,12 +5,20 @@
#include "game/g_world.h"
#include "model.h"
-G_Entity *G_Entity_New(G_Entity *parent, const G_Entity_Class *eclass)
+G_Entity *G_Entity_New(G_Entity *parent, const G_Entity_Class *eclass, const G_Entity_Position *position)
{
G_Entity *entity;
NUint32 childindex = 0;
if (!eclass)
return NULL;
+ if (!eclass->codeclass->name)
+ {
+ Console_Printf("G_Entity_New: no code class found for classname \"%s\"\n", eclass->classname);
+ // if editing, we should keep the unrecognized entities so that the
+ // user can change them to something else
+ if (!G.editing)
+ return NULL;
+ }
if (parent)
{
for (childindex = 0;childindex < G_ENTITY_CHILDREN;childindex++)
@@ -23,6 +31,8 @@
return NULL;
}
}
+ if (!position)
+ position = &GS.identityposition;
// TODO: add a timeout after freeing an entity before it will be reused? (if so this will need to scan twice if it can't find one with the timeout)
for (entity = G.entities + G.allocentity;G.allocentity < G_MAX_ENTITIES;G.allocentity++, entity++)
{
@@ -40,9 +50,10 @@
entity->owner = parent;
parent->children[childindex] = entity;
}
- // now set up basic things that are generally wanted, to save code in the spawn functions
+ entity->position = *position;
if (entity->eclass->modelname && entity->eclass->modelname[0])
G_Entity_SetModel(entity, entity->eclass->modelname);
+ entity->lifetime = entity->eclass->lifetime;
return entity;
}
}
@@ -52,13 +63,6 @@
void G_Entity_Spawn(G_Entity *entity)
{
- if (!entity->eclass)
- {
- Console_Printf("G_Entity_Spawn: NULL eclass\n");
- entity->eclass = G_EntityClass_ByNumber(0);
- }
- if (!entity->modelindex && entity->eclass->modelname)
- G_Entity_SetModel(entity, entity->eclass->modelname);
if (entity->eclass->codeclass->spawn)
{
entity->eclass->codeclass->spawn(entity);
@@ -69,38 +73,6 @@
G_Entity_Relink(entity);
}
-void G_Entity_SpawnFromFields(G_Entity *entity)
-{
- char *classname, *model, *cubemapname;
- Nvec3 origin, angles;
- Nvec scale;
- classname = G_Entity_FieldValue_String(entity, "classname");
- entity->eclass = G_EntityClass_ByName(classname);
- // set up the most general fields to save code in spawn functions
- G_Entity_FieldValue_Vector(entity, "origin", origin);
- G_Entity_FieldValue_Vector(entity, "angles", angles);
- scale = G_Entity_FieldValue_Double(entity, "scale");
- if (!scale)
- scale = 1;
- Matrix4x4_CreateFromQuakeEntity(&entity->matrix, origin[0], origin[1], origin[2], angles[0], angles[1], angles[2], scale);
- G_Entity_FieldValue_Vector(entity, "color", entity->lightcolor);
- cubemapname = G_Entity_FieldValue_String(entity, "cubemap");
- if (cubemapname)
- entity->lightcubemap = Resource_IndexForName(cubemapname, RESOURCETYPE_TEXTURE, 0, 0);
- model = G_Entity_FieldValue_String(entity, "model");
- if (model)
- G_Entity_SetModel(entity, model);
- if (!G.editing)
- G_Entity_RemoveFields(entity);
- G_Entity_Spawn(entity);
- if (!entity->eclass->codeclass->name)
- {
- Console_Printf("G_Entity_SpawnFromFields: no class found for classname \"%s\"\n", classname ? classname : "");
- if (!G.editing)
- G_Entity_Remove(entity);
- }
-}
-
static void G_Entity_Unlink(G_Entity *entity);
void G_Entity_Remove(G_Entity *entity)
{
@@ -138,7 +110,7 @@
if (entity->transforms)
Mem_Free(&entity->transforms);
// remove attached fields (which only exist in editing mode)
- G_Entity_RemoveFields(entity);
+ StringKeys_FreeKeys(&entity->keys);
// clear the entity completely
memset(entity, 0, sizeof(*entity));
// reset allocentity to a level that will find this freshly freed entity
@@ -153,40 +125,46 @@
G_Entity_Remove(entity->children[childindex]);
}
-void G_Entity_RemoveFields(G_Entity *entity)
-{
- G_Entity_Field *field, *fieldnext;
- for (field = entity->fields;field;field = fieldnext)
- {
- fieldnext = field->next;
- String_Free(&field->key);
- String_Free(&field->value);
- Mem_Free(&field);
- }
- entity->fields = NULL;
-}
-
void G_Entity_SpawnInventoryChildren(G_Entity *entity)
{
NUint32 i;
for (i = 0;i < G_ENTITYCLASS_INVENTORY_MAX;i++)
{
- if (entity->eclass->inventory[i].quantity > 0)
+ if (entity->eclass->inventory[i].codename)
{
const G_Entity_Class *itemeclass = G_EntityClass_ByName(entity->eclass->inventory[i].codename);
if (itemeclass)
{
- G_Entity *item = G_Entity_New(entity, itemeclass);
- item->quantity = entity->eclass->inventory[i].quantity;
+ G_Entity *item = G_Entity_New(entity, itemeclass, &entity->position);
+ item->attachment_entity = entity;
+ item->attachment_transformindex = Model_GetTransformNumberForName(entity->modelindex, entity->eclass->inventory[i].transformname) + 1;
+ item->attachment_matrix = GS.identityposition.m;
G_Entity_Spawn(item);
}
else
Console_Printf("G_Entity_SpawnInventoryChildren: Can't find entity class for %s.I%iC\n", entity->eclass->codename, i + 1);
}
}
- // TODO; spawn inventory entities and attach to player model
}
+void G_Entity_GetTransformMatrix(G_Entity *entity, NUint32 transformindex, matrix4x4_t *result)
+{
+ if (index >= 1 && index <= entity->numtransforms)
+ Matrix4x4_Concat(result, &entity->position.m, entity->transforms + (transformindex - 1));
+ else
+ *result = entity->position.m;
+}
+
+void G_Entity_UpdateAttachment(G_Entity *entity)
+{
+ matrix4x4_t parentmatrix;
+ if (!entity->attachment_entity)
+ return;
+ G_Entity_GetMatrix(entity->attachment_entity, entity->attachment_index, &parentmatrix);
+ Matrix4x4_Concat(&entity->position.m, &parentmatrix, &entity->attachment_matrix);
+ G_Entity_Relink(entity);
+}
+
void G_World_UnlinkSurface(G_Entity_Surface *surface);
void G_World_LinkSurface(G_Entity_Surface *surface);
@@ -236,6 +214,18 @@
G_Entity_SetModelIndex(entity, Resource_IndexForName(modelname, RESOURCETYPE_MODEL, 0, 0));
}
+void G_Entity_SetAnimation(G_Entity *entity, G_Entity_AnimationState *state, G_Entity_AnimationType type, const char *modelanimname)
+{
+ state->type = type;
+ state->time = 0;
+ state->resourceindex = Resource_IndexForName(modelanimname, RESOURCETYPE_MODELANIM, 0, 0);
+}
+
+void G_Entity_Animation(G_Entity *entity, G_Entity_AnimationState *state)
+{
+ state->time += G.frametime;
+}
+
// FIXME: move these to g_world.c
void G_World_UnlinkSurface(G_Entity_Surface *surface)
{
@@ -284,10 +274,13 @@
G_Entity_Unlink(entity);
+ // update the inverse matrix
+ Matrix4x4_Invert_Simple(&entity->position.inversem, &entity->position.m);
+
if (entity->eclass->codeclass->scopeflags & G_SCOPE_RENDER_LIGHTSOURCE)
{
- Matrix4x4_OriginFromMatrix(&entity->matrix, entity->cullorigin);
- entity->cullradius = Matrix4x4_ScaleFromMatrix(&entity->matrix);
+ Matrix4x4_OriginFromMatrix(&entity->position.m, entity->cullorigin);
+ entity->cullradius = Matrix4x4_ScaleFromMatrix(&entity->position.m);
entity->cullmins[0] = entity->cullorigin[0] - entity->cullradius;
entity->cullmins[1] = entity->cullorigin[1] - entity->cullradius;
entity->cullmins[2] = entity->cullorigin[2] - entity->cullradius;
@@ -310,9 +303,9 @@
meshlocalcullorigin[0] = (meshlocalmins[0] + meshlocalmaxs[0]) * 0.5;
meshlocalcullorigin[1] = (meshlocalmins[1] + meshlocalmaxs[1]) * 0.5;
meshlocalcullorigin[2] = (meshlocalmins[2] + meshlocalmaxs[2]) * 0.5;
- Matrix4x4_Transform(&entity->matrix, meshlocalcullorigin, surface->cullorigin);
- // TODO: scale radius based on longest vector in entity->matrix?
- surface->cullradius = Matrix4x4_ScaleFromMatrix(&entity->matrix) * VectorDistance(meshlocalcullorigin, meshlocalmaxs);
+ Matrix4x4_Transform(&entity->position.m, meshlocalcullorigin, surface->cullorigin);
+ // TODO: scale radius based on longest vector in entity->position.m?
+ surface->cullradius = Matrix4x4_ScaleFromMatrix(&entity->position.m) * VectorDistance(meshlocalcullorigin, meshlocalmaxs);
VectorCopy(surface->cullorigin, surface->cullmins);
VectorCopy(surface->cullorigin, surface->cullmaxs);
// TODO: optimize unrotated case
@@ -322,7 +315,7 @@
localpoint[0] = i & 1 ? meshlocalmaxs[0] : meshlocalmins[0];
localpoint[1] = i & 2 ? meshlocalmaxs[1] : meshlocalmins[1];
localpoint[2] = i & 4 ? meshlocalmaxs[2] : meshlocalmins[2];
- Matrix4x4_Transform(&entity->matrix, localpoint, point);
+ Matrix4x4_Transform(&entity->position.m, localpoint, point);
surface->cullmins[0] = Min(surface->cullmins[0], point[0]);
surface->cullmins[1] = Min(surface->cullmins[1], point[1]);
surface->cullmins[2] = Min(surface->cullmins[2], point[2]);
@@ -362,18 +355,18 @@
cullorigin[0] = (entitylocalmins[0] + entitylocalmaxs[0]) * 0.5;
cullorigin[1] = (entitylocalmins[1] + entitylocalmaxs[1]) * 0.5;
cullorigin[2] = (entitylocalmins[2] + entitylocalmaxs[2]) * 0.5;
- Matrix4x4_Transform(&entity->matrix, cullorigin, entity->cullorigin);
- // TODO: scale radius based on longest vector in entity->matrix?
- entity->cullradius = Matrix4x4_ScaleFromMatrix(&entity->matrix) * VectorDistance(cullorigin, entitylocalmaxs);
+ Matrix4x4_Transform(&entity->position.m, cullorigin, entity->cullorigin);
+ // TODO: scale radius based on longest vector in entity->position.m?
+ entity->cullradius = Matrix4x4_ScaleFromMatrix(&entity->position.m) * VectorDistance(cullorigin, entitylocalmaxs);
// TODO: link into culling grid for collision detection
}
else
{
// no surfaces, so culling box is just a point
- entity->cullorigin[0] = entity->matrix.m[0][3];
- entity->cullorigin[1] = entity->matrix.m[1][3];
- entity->cullorigin[2] = entity->matrix.m[2][3];
+ entity->cullorigin[0] = entity->position.m.m[0][3];
+ entity->cullorigin[1] = entity->position.m.m[1][3];
+ entity->cullorigin[2] = entity->position.m.m[2][3];
entity->cullradius = 0;
VectorCopy(entity->cullorigin, entity->cullmins);
VectorCopy(entity->cullorigin, entity->cullmaxs);
@@ -388,7 +381,7 @@
matrix4x4_t newmatrix;
G_Trace trace;
- if (VectorLength2(self->velocity) < (1.0 / 1024.0))
+ if (VectorLength2(self->position.velocity) < (1.0 / 1024.0))
{
// no movement
return;
@@ -400,24 +393,24 @@
if (!scope)
{
// noclip
- self->matrix.m[0][3] = self->matrix.m[0][3] + G.frametime * self->velocity[0];
- self->matrix.m[1][3] = self->matrix.m[1][3] + G.frametime * self->velocity[1];
- self->matrix.m[2][3] = self->matrix.m[2][3] + G.frametime * self->velocity[2];
+ self->position.m.m[0][3] = self->position.m.m[0][3] + G.frametime * self->position.velocity[0];
+ self->position.m.m[1][3] = self->position.m.m[1][3] + G.frametime * self->position.velocity[1];
+ self->position.m.m[2][3] = self->position.m.m[2][3] + G.frametime * self->position.velocity[2];
G_Entity_Relink(self);
return;
}
for (bump = 0, t = 1;bump < 16 && t >= (1.0 / 128.0);bump++)
{
- newmatrix = self->matrix;
- newmatrix.m[0][3] = self->matrix.m[0][3] + t * G.frametime * self->velocity[0];
- newmatrix.m[1][3] = self->matrix.m[1][3] + t * G.frametime * self->velocity[1];
- newmatrix.m[2][3] = self->matrix.m[2][3] + t * G.frametime * self->velocity[2];
+ newmatrix = self->position.m;
+ newmatrix.m[0][3] = self->position.m.m[0][3] + t * G.frametime * self->position.velocity[0];
+ newmatrix.m[1][3] = self->position.m.m[1][3] + t * G.frametime * self->position.velocity[1];
+ newmatrix.m[2][3] = self->position.m.m[2][3] + t * G.frametime * self->position.velocity[2];
- G_World_Trace_Brush(&trace, &self->collisionbrush, &self->matrix, &newmatrix, self, scope);
+ G_World_Trace_Brush(&trace, &self->collisionbrush, &self->position.m, &newmatrix, self, scope);
if (trace.impact_fraction == 1)
{
- self->matrix = trace.impact_matrix;
+ self->position.m = trace.impact_matrix;
break;
}
@@ -429,7 +422,7 @@
matrix4x4_t matrix2;
matrix4x4_t newmatrix2;
// trace again, but higher
- matrix2 = self->matrix;
+ matrix2 = self->position.m;
matrix2.m[2][3] += stepheight;
newmatrix2 = newmatrix;
newmatrix2.m[2][3] += stepheight;
@@ -451,8 +444,8 @@
VectorCopy(trace.impact_normal, self->groundnormal);
}
- self->matrix = trace.impact_matrix;
- VectorReflect(self->velocity, bounce, trace.impact_normal, self->velocity);
+ self->position.m = trace.impact_matrix;
+ VectorReflect(self->position.velocity, bounce, trace.impact_normal, self->position.velocity);
t -= t * trace.impact_fraction;
}
@@ -463,12 +456,12 @@
G_Trace trace2;
matrix4x4_t matrix2;
matrix4x4_t newmatrix2;
- matrix2 = self->matrix;
+ matrix2 = self->position.m;
newmatrix2 = matrix2;
newmatrix2.m[2][3] -= stepheight;
G_World_Trace_Brush(&trace2, &self->collisionbrush, &matrix2, &newmatrix2, self, scope);
if (trace2.impact_fraction < 1)
- self->matrix = trace2.impact_matrix;
+ self->position.m = trace2.impact_matrix;
}
*/
@@ -486,15 +479,15 @@
if (!jumpspeed)
{
// apply stopspeed
- VectorReflect(self->velocity, 0, self->groundnormal, groundwishdir);
+ VectorReflect(self->position.velocity, 0, self->groundnormal, groundwishdir);
VectorNormalize(groundwishdir);
- f = DotProduct(self->velocity, groundwishdir);
+ f = DotProduct(self->position.velocity, groundwishdir);
f = Min(f, groundstopspeed * G.frametime);
if (f > 0)
- VectorMA(self->velocity, -f, groundwishdir, self->velocity);
+ VectorMA(self->position.velocity, -f, groundwishdir, self->position.velocity);
// apply friction
f = Bound(0, G.frametime * groundfriction, 1);
- VectorLerp(self->velocity, f, self->groundentity->velocity, self->velocity);
+ VectorLerp(self->position.velocity, f, self->groundentity->position.velocity, self->position.velocity);
}
if (wishvel)
{
@@ -505,47 +498,47 @@
// normalize the groundwishdir, we only wanted the direction
VectorNormalize(groundwishdir);
wishspeed = VectorLength(wishvel);
- f = Min(wishspeed * groundaccel * G.frametime, wishspeed - DotProduct(self->velocity, groundwishdir));
+ f = Min(wishspeed * groundaccel * G.frametime, wishspeed - DotProduct(self->position.velocity, groundwishdir));
if (f > 0)
{
// apply acceleration
- VectorMA(self->velocity, f, groundwishdir, self->velocity);
+ VectorMA(self->position.velocity, f, groundwishdir, self->position.velocity);
}
}
// add jump impulse along ground normal
if (jumpspeed)
- VectorMA(self->velocity, jumpspeed, self->groundnormal, self->velocity);
+ VectorMA(self->position.velocity, jumpspeed, self->groundnormal, self->position.velocity);
// apply gravity acceleration
- VectorAdd(self->velocity, gravityimpulse, self->velocity);
+ VectorAdd(self->position.velocity, gravityimpulse, self->position.velocity);
// add another impulse to counteract the sliding that results from gravity
VectorReflect(gravityimpulse, 0, self->groundnormal, countergravityimpulse);
- VectorSubtract(self->velocity, countergravityimpulse, self->velocity);
+ VectorSubtract(self->position.velocity, countergravityimpulse, self->position.velocity);
}
else
{
// apply stopspeed
- f = VectorLength(self->velocity);
+ f = VectorLength(self->position.velocity);
if (f > airstopspeed)
{
f = 1 - airstopspeed * G.frametime / f;
- VectorScale(self->velocity, f, self->velocity);
+ VectorScale(self->position.velocity, f, self->position.velocity);
}
else
- VectorClear(self->velocity);
+ VectorClear(self->position.velocity);
// apply friction
f = Bound(0, 1 - G.frametime * airfriction, 1);
- VectorScale(self->velocity, f, self->velocity);
+ VectorScale(self->position.velocity, f, self->position.velocity);
if (wishvel)
{
// apply acceleration
f = Bound(-1, G.frametime * airaccel, 1);
- VectorMA(self->velocity, f, wishvel, self->velocity);
+ VectorMA(self->position.velocity, f, wishvel, self->position.velocity);
}
// apply gravity acceleration
- VectorAdd(self->velocity, gravityimpulse, self->velocity);
+ VectorAdd(self->position.velocity, gravityimpulse, self->position.velocity);
}
if (thrustvel)
- VectorMA(self->velocity, G.frametime, thrustvel, self->velocity);
+ VectorMA(self->position.velocity, G.frametime, thrustvel, self->position.velocity);
}
static Collision_Brush boxbrush;
@@ -613,98 +606,6 @@
Collision_Brush_UpdateCullingData(&entity->collisionbrush);
}
-void G_Entity_SetField(G_Entity *entity, const char *key, const char *value)
-{
- G_Entity_Field *field, **nextpointer;
- if (!String_ICompare(value, ""))
- {
- // remove a field
- for (nextpointer = &entity->fields, field = *nextpointer;field;nextpointer = &field->next, field = *nextpointer)
- {
- if (!String_ICompare(field->key, key))
- {
- String_Free(&field->key);
- String_Free(&field->value);
- Mem_Free(&field);
- // unlink the field by updating the previous field's next
- // pointer to point to the next field after the removed field
- *nextpointer = field->next;
- return;
- }
- }
- // no field found
- }
- else
- {
- // add or update a field
- for (nextpointer = &entity->fields, field = *nextpointer;field;nextpointer = &field->next, field = *nextpointer)
- {
- if (!String_ICompare(field->key, key))
- {
- // update the existing field
- String_Set(&field->key, GS.memzone, key);
- String_Set(&field->value, GS.memzone, value);
- return;
- }
- }
- // add the field
- *nextpointer = field = Mem_Alloc(GS.memzone, sizeof(G_Entity_Field));
- String_Set(&field->key, GS.memzone, key);
- String_Set(&field->value, GS.memzone, value);
- }
-}
-
-char *G_Entity_FieldValue_String(G_Entity *entity, const char *key)
-{
- G_Entity_Field *field;
- for (field = entity->fields;field;field = field->next)
- if (!String_ICompare(field->key, key))
- return field->value;
- return NULL;
-}
-
-NSint32 G_Entity_FieldValue_Integer(G_Entity *entity, const char *key)
-{
- char *value = G_Entity_FieldValue_String(entity, key);
- if (value)
- {
- while (*value && *value <= ' ')
- value++;
- return atoi(value);
- }
- return 0;
-}
-
-Ndouble G_Entity_FieldValue_Double(G_Entity *entity, const char *key)
-{
- char *value = G_Entity_FieldValue_String(entity, key);
- if (value)
- {
- while (*value && *value <= ' ')
- value++;
- return atof(value);
- }
- return 0;
-}
-
-void G_Entity_FieldValue_Vector(G_Entity *entity, const char *key, Nvec3 vector)
-{
- NUint32 i;
- char *value = G_Entity_FieldValue_String(entity, key);
- VectorClear(vector);
- if (value)
- {
- for (i = 0;i < 3;i++)
- {
- while (*value && *value <= ' ')
- value++;
- vector[i] = atof(value);
- while (*value > ' ')
- value++;
- }
- }
-}
-
Nbool G_Entity_ReadPacket(G_PacketBuffer *buffer, NUint32 entityclassnumber)
{
// read 16bit entitynum
@@ -749,7 +650,7 @@
if (G.client_networkentityindex[entitynum] < 0)
{
// create a new entity
- entity = G_Entity_New(NULL, eclass);
+ entity = G_Entity_New(NULL, eclass, &GS.identityposition);
// network index this local entity represents
entity->networkindex = entitynum;
// backwards index from the network index to this local entity
@@ -781,8 +682,8 @@
NUint32 clientindex;
GS_Client *client;
for (clientindex = 0, client = GS.clients;clientindex < G_MAX_CLIENTS;clientindex++, client++)
- if (client->netconnection)
- client->netconnection->entitypriority[entitynumber] = Max(client->netconnection->entitypriority[entitynumber], 1);
+ if (client->netconnection && client->netconnection->entitypriority[entitynumber] < 1)
+ client->netconnection->entitypriority[entitynumber] = 1;
}
G_Entity *G_Entity_Find_CodeName(G_Entity *previous, const char *value)
Modified: trunk/game/g_entity.h
===================================================================
--- trunk/game/g_entity.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_entity.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -6,30 +6,27 @@
// G_Entity member functions:
// creation/destruction of entities
-G_Entity *G_Entity_New(G_Entity *parent, const G_Entity_Class *eclass);
+G_Entity *G_Entity_New(G_Entity *parent, const G_Entity_Class *eclass, const G_Entity_Position *position);
void G_Entity_Spawn(G_Entity *entity);
-void G_Entity_SpawnFromFields(G_Entity *entity);
void G_Entity_Remove(G_Entity *entity);
void G_Entity_RemoveChildren(G_Entity *entity);
-void G_Entity_RemoveFields(G_Entity *entity);
void G_Entity_SpawnInventoryChildren(G_Entity *entity);
+// attaching entities to eachother
+void G_Entity_GetMatrix(G_Entity *entity, NUint32 index, matrix4x4_t *result);
+void G_Entity_UpdateAttachment(G_Entity *entity);
// changing an entity's model
G_Entity_Surface *G_Entity_AddSurface(G_Entity *entity, NUint32 meshindex);
void G_Entity_RemoveSurface(G_Entity *entity, G_Entity_Surface *surface);
void G_Entity_SetModelIndex(G_Entity *entity, NUint32 modelindex);
void G_Entity_SetModel(G_Entity *entity, const char *modelname);
+// animation of an entity's model
+void G_Entity_Animation(G_Entity *entity, G_Entity_AnimationState *state);
// entity physics
void G_Entity_Relink(G_Entity *entity);
void G_Entity_Move(G_Entity *self, NUint32 scope, Nvec stepheight, Nvec bounce);
void G_Entity_PlayerPhysics(G_Entity *self, Nvec3 wishvel, Nvec groundfriction, Nvec groundaccel, Nvec stopspeed, Nvec airfriction, Nvec airaccel, Nvec airstopspeed, Nvec jumpspeed, Nvec gravityscale, Nvec3 thrustvel);
void G_Entity_SetBrush_Box(G_Entity *entity, const Nvec3 boxmins, const Nvec3 boxmaxs);
void G_Entity_SetBrush_Point(G_Entity *entity, const Nvec3 point);
-// editing
-void G_Entity_SetField(G_Entity *entity, const char *key, const char *value);
-Ndouble G_Entity_FieldValue_Double(G_Entity *entity, const char *key);
-NSint32 G_Entity_FieldValue_Integer(G_Entity *entity, const char *key);
-char *G_Entity_FieldValue_String(G_Entity *entity, const char *key);
-void G_Entity_FieldValue_Vector(G_Entity *entity, const char *key, Nvec3 vector);
// networking
Nbool G_Entity_ReadPacket(G_PacketBuffer *buffer, NUint32 entityclassnumber);
void G_Entity_SendNetworkUpdate(G_Entity *entity);
Modified: trunk/game/g_entityclass.c
===================================================================
--- trunk/game/g_entityclass.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_entityclass.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -27,7 +27,7 @@
static void G_Object_Light_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
- G_PacketBuffer_WriteMatrix(buffer, &self->matrix, true, true, true);
+ G_PacketBuffer_WritePosition(buffer, &self->position, true, true, true, false, false);
G_PacketBuffer_WriteColorVector16(buffer, self->lightcolor);
G_PacketBuffer_WriteResourceIndex_NoCache(buffer, self->lightcubemap);
G_PacketBuffer_WriteBool(buffer, self->lightcastshadows);
@@ -38,7 +38,7 @@
static void G_Object_Light_ReadPacket(G_Entity *self, G_PacketBuffer *buffer, Nbool reset)
{
- G_PacketBuffer_ReadMatrix(buffer, &self->matrix, true, true, true);
+ G_PacketBuffer_ReadPosition(buffer, &self->position, true, true, true, false, false);
G_PacketBuffer_ReadColorVector16(buffer, self->lightcolor);
self->lightcubemap = G_PacketBuffer_ReadResourceIndex_NoCache(buffer, RESOURCETYPE_TEXTURE);
self->lightcastshadows = G_PacketBuffer_ReadBool(buffer);
@@ -61,13 +61,13 @@
static void G_Object_Model_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
- G_PacketBuffer_WriteMatrix(buffer, &self->matrix, true, true, true);
+ G_PacketBuffer_WritePosition(buffer, &self->position, true, true, true, false, false);
G_PacketBuffer_WriteResourceIndex_NoCache(buffer, self->modelindex);
}
static void G_Object_Model_ReadPacket(G_Entity *self, G_PacketBuffer *buffer, Nbool reset)
{
- G_PacketBuffer_ReadMatrix(buffer, &self->matrix, true, true, true);
+ G_PacketBuffer_ReadPosition(buffer, &self->position, true, true, true, false, false);
G_Entity_SetModelIndex(self, G_PacketBuffer_ReadResourceIndex_NoCache(buffer, RESOURCETYPE_MODEL));
}
@@ -125,6 +125,8 @@
user->localinput_pressedbuttonbits = 0;
VectorClear(user->localinput_relativeviewangles);
+ self->buttons = buttonbits;
+
speed = (user->flymode || user->noclipmode) ? 100 : self->eclass->speed;
VectorAdd(self->viewangles, relativeviewangles, self->viewangles);
@@ -132,17 +134,20 @@
self->viewangles[1] -= 360 * floor(self->viewangles[1] / 360);
self->viewangles[2] = 0;
+ G_Entity_Animation(self, &self->anim_head);
+ G_Entity_Animation(self, &self->anim_torso);
+ G_Entity_Animation(self, &self->anim_legs);
+
VectorClear(movement);
- if (buttonbits & G_BUTTON_MOVEFORWARD)
- {movement[0] += 1;}
- if (buttonbits & G_BUTTON_MOVEBACKWARD) {movement[0] -= 1;}
- if (buttonbits & G_BUTTON_MOVELEFT) {movement[1] += 1;}
- if (buttonbits & G_BUTTON_MOVERIGHT) {movement[1] -= 1;}
+ if (buttonbits & G_BUTTON_MOVEFORWARD) movement[0] += 1;
+ if (buttonbits & G_BUTTON_MOVEBACKWARD) movement[0] -= 1;
+ if (buttonbits & G_BUTTON_MOVELEFT) movement[1] += 1;
+ if (buttonbits & G_BUTTON_MOVERIGHT) movement[1] -= 1;
if (user->flymode || user->noclipmode)
{
- if (buttonbits & G_BUTTON_MOVEUP) {movement[2] += 1;}
- if (buttonbits & G_BUTTON_MOVEDOWN) {movement[2] -= 1;}
- Matrix4x4_CreateFromQuakeEntity(&newmatrix, self->matrix.m[0][3], self->matrix.m[1][3], self->matrix.m[2][3] + 0.7, self->viewangles[0], self->viewangles[1], self->viewangles[2], speed);
+ if (buttonbits & G_BUTTON_MOVEUP) movement[2] += 1;
+ if (buttonbits & G_BUTTON_MOVEDOWN) movement[2] -= 1;
+ Matrix4x4_CreateFromQuakeEntity(&newmatrix, self->position.m.m[0][3], self->position.m.m[1][3], self->position.m.m[2][3] + 0.7, self->viewangles[0], self->viewangles[1], self->viewangles[2], speed);
}
else
Matrix4x4_CreateFromQuakeEntity(&newmatrix, 0, 0, 0, 0, self->viewangles[1], 0, speed);
@@ -162,21 +167,21 @@
int j;
for (j = 0; j < 3; j++)
{
- if (IsNAN(self->velocity[j]))
- self->velocity[j] = 0;
+ if (IsNAN(self->position.velocity[j]))
+ self->position.velocity[j] = 0;
}
}
G_Entity_Move(self, user->noclipmode ? 0 : G_SCOPE_BLOCK_PLAYER, self->eclass->stepheight, 0);
- //Matrix4x4_ConcatQuakeEntity(&self->matrix, movement[0], movement[1], movement[2], turn[0], turn[1], turn[2], 1);
- //Matrix4x4_Normalize(&self->matrix, &self->matrix);
+ //Matrix4x4_ConcatQuakeEntity(&self->position.m, movement[0], movement[1], movement[2], turn[0], turn[1], turn[2], 1);
+ //Matrix4x4_Normalize(&self->position.m, &self->position.m);
if (user->client)
{
if (user->client->netconnection)
{
- Matrix4x4_OriginFromMatrix(&self->matrix, user->client->netconnection->eyeorigin);
+ Matrix4x4_OriginFromMatrix(&self->position.m, user->client->netconnection->eyeorigin);
user->client->netconnection->eyeradius = 1000000; // 1000km
}
else
@@ -187,7 +192,7 @@
if (GS.localuserindex == self->localuserindex)
{
// set up the view matrix for the player
- Matrix4x4_CreateFromQuakeEntity(&G.cameramatrix, self->matrix.m[0][3], self->matrix.m[1][3], self->matrix.m[2][3] + 0.7, self->viewangles[0], self->viewangles[1], self->viewangles[2], 1);
+ Matrix4x4_CreateFromQuakeEntity(&G.cameramatrix, self->position.m.m[0][3], self->position.m.m[1][3], self->position.m.m[2][3] + 0.7, self->viewangles[0], self->viewangles[1], self->viewangles[2], 1);
}
}
}
@@ -200,7 +205,7 @@
static void G_Object_Infantry_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
G_PacketBuffer_Write16(buffer, GS.client_remotefromlocaluserindex[self->localuserindex]);
- G_PacketBuffer_WriteMatrix(buffer, &self->matrix, true, false, false);
+ G_PacketBuffer_WritePosition(buffer, &self->position, true, false, false, false, false);
G_PacketBuffer_WriteAngles16(buffer, self->viewangles);
}
@@ -208,7 +213,7 @@
{
// TODO: bounds check userindex
self->localuserindex = GS.client_localfromremoteuserindex[G_PacketBuffer_Read16(buffer)];
- G_PacketBuffer_ReadMatrix(buffer, &self->matrix, true, false, false);
+ G_PacketBuffer_ReadPosition(buffer, &self->position, true, false, false, false, false);
G_PacketBuffer_ReadAngles16(buffer, self->viewangles);
if (reset)
G_Entity_SetBrush_Box(self, playermins, playermaxs);
@@ -342,16 +347,63 @@
{
}
+static void G_Object_Weapon_LaunchProjectile(G_Entity *self)
+{
+ G_Entity_Position position;
+ G_Entity *projectile;
+ const G_Entity_Class *projectileclass;
+ Nvec3 speedvec;
+ position = self->position;
+ projectileclass = G_EntityClass_ByName(self->eclass->projectilecodename);
+ VectorSet(speedvec, projectileclass->speed, 0, 0);
+ Matrix4x4_Transform3x3(&position.m, speedvec, position.velocity);
+ // TODO: rifled bullet spin?
+ projectile = G_Entity_New(NULL, projectileclass, &position);
+ //if (!projectile)
+ // return;
+}
+
static void G_Object_Weapon_Frame(G_Entity *self)
{
+ if (self->attachment_entity)
+ G_Entity_UpdateAttachment(self);
+ self->attackdelay -= G.frametime;
+ if (self->attackdelay <= 0)
+ {
+ if (self->owner->buttons & G_BUTTON_FIRE1)
+ {
+ G_Object_Weapon_LaunchProjectile(self);
+ self->attackdelay += self->eclass->autorefire;
+ G_Entity_SendNetworkUpdate(self);
+ }
+ else
+ self->attackdelay = 0;
+ }
}
static void G_Object_Weapon_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
+ if (self->owner)
+ {
+ G_PacketBuffer_WriteBool(buffer, true);
+ G_PacketBuffer_WriteEntityAsIndex(buffer, self->owner);
+ G_PacketBuffer_Write16(buffer, self->attachment_index);
+ }
+ else
+ G_PacketBuffer_WriteBool(buffer, false);
+ // we don't need much precision on how recently the gun was fired, so use
+ // an 8bit fraction-of-refire-time byte to save space
+ G_PacketBuffer_WriteClamped8(buffer, self->attackdelay, 255.0f / self->eclass->autorefire);
}
static void G_Object_Weapon_ReadPacket(G_Entity *self, G_PacketBuffer *buffer, Nbool reset)
{
+ if (G_PacketBuffer_ReadBool(buffer))
+ {
+ self->owner = G_PacketBuffer_ReadEntityAsIndex(buffer);
+ self->attachment_index = G_PacketBuffer_Read16(buffer);
+ }
+ G_PacketBuffer_ReadClamped8(buffer, 255.0f / self->eclass->autorefire);
}
static void G_Object_Ammo_Spawn(G_Entity *self)
@@ -384,18 +436,33 @@
static void G_Object_Projectile_Frame(G_Entity *self)
{
+ // TODO: use a better physics function (one that handles spin)
+ G_Entity_PlayerPhysics(self, NULL, self->eclass->friction, self->eclass->acceleration, self->eclass->stopspeed, self->eclass->airfriction, self->eclass->airacceleration, self->eclass->airstopspeed, 0, 1, NULL);
+
+ G_Entity_Move(self, G_SCOPE_BLOCK_PROJECTILE, 0, 0);
+
+ self->lifetime -= G.frametime;
+ if (self->lifetime <= 0)
+ G_Entity_Remove(self);
}
static void G_Object_Projectile_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
+ // TODO: should we send only origin and velocity and try to guess the rest
+ // to save space, or be accurate and send origin rotation velocity spin?
+ G_PacketBuffer_WritePosition(buffer, &self->position, true, true, false, true, true);
+ G_PacketBuffer_WriteClamped8(buffer, self->lifetime, 255.0f / self->eclass->lifetime);
}
static void G_Object_Projectile_ReadPacket(G_Entity *self, G_PacketBuffer *buffer, Nbool reset)
{
+ G_PacketBuffer_ReadPosition(buffer, &self->position, true, true, false, true, true);
+ self->lifetime = G_PacketBuffer_ReadClamped8(buffer, 255.0f / self->eclass->lifetime);
}
static void G_Object_Explosion_Spawn(G_Entity *self)
{
+ // TODO: do damage
}
static void G_Object_Explosion_Remove(G_Entity *self)
@@ -404,14 +471,21 @@
static void G_Object_Explosion_Frame(G_Entity *self)
{
+ self->lifetime -= G.frametime;
+ if (self->lifetime <= 0)
+ G_Entity_Remove(self);
}
static void G_Object_Explosion_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
+ G_PacketBuffer_WritePosition(buffer, &self->position, true, false, false, false, false);
+ G_PacketBuffer_WriteClamped8(buffer, self->lifetime, 255.0f / self->eclass->lifetime);
}
static void G_Object_Explosion_ReadPacket(G_Entity *self, G_PacketBuffer *buffer, Nbool reset)
{
+ G_PacketBuffer_ReadPosition(buffer, &self->position, true, false, false, false, false);
+ self->lifetime = G_PacketBuffer_ReadClamped8(buffer, 255.0f / self->eclass->lifetime);
}
static void G_Object_Light_Attached_Spawn(G_Entity *self)
@@ -429,7 +503,7 @@
G_Entity_Remove(self);
return;
}
- Matrix4x4_Concat(&self->matrix, &self->owner->matrix, &self->lightmatrix);
+ Matrix4x4_Concat(&self->position.m, &self->owner->position.m, &self->lightmatrix);
G_Entity_Relink(self);
}
@@ -451,7 +525,7 @@
model = Resource_GetData(self->modelindex);
if (model)
G_Entity_SetBrush_Box(self, model->basecullmins, model->basecullmaxs);
- light = G_Entity_New(self, G_EntityClass_ByName("light_attached"));
+ light = G_Entity_New(self, G_EntityClass_ByName("light_attached"), &self->position);
Matrix4x4_CreateFromQuakeEntity(&light->lightmatrix, 0, 3.5, 4, 0, 0, 0, 30);
VectorSet(light->lightcolor, 1, 0.9, 0.2);
light->lightcastshadows = true;
@@ -474,21 +548,21 @@
static void G_Object_Vehicle_RockBore_WritePacket(G_Entity *self, G_PacketBuffer *buffer)
{
- G_PacketBuffer_WriteMatrix(buffer, &self->matrix, true, true, true);
+ G_PacketBuffer_WritePosition(buffer, &self->position, true, true, true, true, true);
}
static void G_Object_Vehicle_RockBore_ReadPacket(G_Entity *self, G_PacketBuffer *buffer, Nbool reset)
{
Model *model;
G_Entity *light;
- G_PacketBuffer_ReadMatrix(buffer, &self->matrix, true, true, true);
+ G_PacketBuffer_ReadPosition(buffer, &self->position, true, true, true, true, true);
if (reset)
{
model = Resource_GetData(self->modelindex);
if (model)
G_Entity_SetBrush_Box(self, model->basecullmins, model->basecullmaxs);
G_Entity_RemoveChildren(self);
- light = G_Entity_New(self, G_EntityClass_ByName("light_attached"));
+ light = G_Entity_New(self, G_EntityClass_ByName("light_attached"), &self->position);
Matrix4x4_CreateFromQuakeEntity(&light->lightmatrix, 0, 3.5, 4, 0, 0, 0, 30);
VectorSet(light->lightcolor, 1, 0.9, 0.2);
light->lightcastshadows = true;
@@ -510,7 +584,7 @@
G_Entity_Remove(self);
return;
}
- Matrix4x4_Concat(&self->matrix, &self->owner->matrix, &self->lightmatrix);
+ Matrix4x4_Concat(&self->position.m, &self->owner->position.m, &self->lightmatrix);
G_Entity_Relink(self);
}
#endif
@@ -701,103 +775,6 @@
G_Entity_Class G_EntityClasses[G_ENTITYCLASS_MAX];
-#if 0
-enum G_CSVColumn
-{
- CSVCOLUMN_CodeName,
- CSVCOLUMN_EnglishName,
- CSVCOLUMN_Class,
- CSVCOLUMN_Model,
- CSVCOLUMN_Mass,
- CSVCOLUMN_Health,
- CSVCOLUMN_Heal,
- CSVCOLUMN_NoRemove,
- CSVCOLUMN_I1Q,
- CSVCOLUMN_I1R,
- CSVCOLUMN_I1C,
- CSVCOLUMN_I2Q,
- CSVCOLUMN_I2R,
- CSVCOLUMN_I2C,
- CSVCOLUMN_I3Q,
- CSVCOLUMN_I3R,
- CSVCOLUMN_I3C,
- CSVCOLUMN_I4Q,
- CSVCOLUMN_I4R,
- CSVCOLUMN_I4C,
- CSVCOLUMN_I5Q,
- CSVCOLUMN_I5R,
- CSVCOLUMN_I5C,
- CSVCOLUMN_I6Q,
- CSVCOLUMN_I6R,
- CSVCOLUMN_I6C,
- CSVCOLUMN_Projectile,
- CSVCOLUMN_SemiRefire,
- CSVCOLUMN_AutoRefire,
- CSVCOLUMN_Speed,
- CSVCOLUMN_Acceleration,
- CSVCOLUMN_TopSpeed,
- CSVCOLUMN_LifeTime,
- CSVCOLUMN_ImpactDelay,
- CSVCOLUMN_FleshDamage,
- CSVCOLUMN_ArmorDamage,
- CSVCOLUMN_Force,
- CSVCOLUMN_DamageRadius,
- CSVCOLUMN_Shake,
- CSVCOLUMN_ShakeRadius,
- CSVCOLUMN_IdleAnim,
- CSVCOLUMN_IdleFPS,
- CSVCOLUMN_END
-};
-
-static const char *csv_columnnames[CSVCOLUMN_END] =
-{
- "CodeName",
- "EnglishName",
- "Class",
- "Model",
- "Mass",
- "Health",
- "Heal",
- "NoRemove",
- "I1Q",
- "I1R",
- "I1C",
- "I2Q",
- "I2R",
- "I2C",
- "I3Q",
- "I3R",
- "I3C",
- "I4Q",
- "I4R",
- "I4C",
- "I5Q",
- "I5R",
- "I5C",
- "I6Q",
- "I6R",
- "I6C",
- "Projectile",
- "SemiRefire",
- "AutoRefire",
- "Speed",
- "Acceleration",
- "TopSpeed",
- "LifeTime",
- "ImpactDelay",
- "FleshDamage",
- "ArmorDamage",
- "Force",
- "DamageRadius",
- "Shake",
- "ShakeRadius",
- "IdleAnim",
- "IdleFPS",
-};
-
-static CSVColumn csv_columnremap[64];
-#endif
-
typedef enum CSVColumnFieldType
{
CSVCOLUMNFIELDTYPE_CHARPOINTER,
@@ -828,24 +805,29 @@
CSVCOLUMNINFO("Health", health, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("Heal", heal, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("NoRemove", noremove, CSVCOLUMNFIELDTYPE_BOOL),
- CSVCOLUMNINFO("I1Q", inventory[0].quantity, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I1R", inventory[0].regen, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I1C", inventory[0].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
- CSVCOLUMNINFO("I2Q", inventory[1].quantity, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I2R", inventory[1].regen, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I2C", inventory[1].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
- CSVCOLUMNINFO("I3Q", inventory[2].quantity, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I3R", inventory[2].regen, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I3C", inventory[2].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
- CSVCOLUMNINFO("I4Q", inventory[3].quantity, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I4R", inventory[3].regen, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I4C", inventory[3].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
- CSVCOLUMNINFO("I5Q", inventory[4].quantity, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I5R", inventory[4].regen, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I5C", inventory[4].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
- CSVCOLUMNINFO("I6Q", inventory[5].quantity, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I6R", inventory[5].regen, CSVCOLUMNFIELDTYPE_NVEC),
- CSVCOLUMNINFO("I6C", inventory[5].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("Respawn", respawn, CSVCOLUMNFIELDTYPE_NVEC),
+ CSVCOLUMNINFO("I0C", inventory[0].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I0B", inventory[0].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I1C", inventory[1].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I1B", inventory[1].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I2C", inventory[2].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I2B", inventory[2].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I3C", inventory[3].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I3B", inventory[3].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I4C", inventory[4].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I4B", inventory[4].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I5C", inventory[5].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I5B", inventory[5].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I6C", inventory[6].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I6B", inventory[6].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I7C", inventory[7].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I7B", inventory[7].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I8C", inventory[8].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I8B", inventory[8].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I9C", inventory[9].codename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("I9B", inventory[9].name, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("AmmoMax", ammomax, CSVCOLUMNFIELDTYPE_NVEC),
+ CSVCOLUMNINFO("AmmoRegen", ammoregen, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("Projectile", projectilecodename, CSVCOLUMNFIELDTYPE_CHARPOINTER),
CSVCOLUMNINFO("SemiRefire", semirefire, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("AutoRefire", autorefire, CSVCOLUMNFIELDTYPE_NVEC),
@@ -863,6 +845,10 @@
CSVCOLUMNINFO("AirStopSpeed", airstopspeed, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("HoverThrust", hoverthrust, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("HoverAltitude", hoveraltitude, CSVCOLUMNFIELDTYPE_NVEC),
+ CSVCOLUMNINFO("Cloaking", cloaking, CSVCOLUMNFIELDTYPE_BOOL),
+ CSVCOLUMNINFO("JumpFlight", jumpflight, CSVCOLUMNFIELDTYPE_BOOL),
+ CSVCOLUMNINFO("CrouchShield", crouchshield, CSVCOLUMNFIELDTYPE_BOOL),
+ CSVCOLUMNINFO("CrouchTurret", crouchturret, CSVCOLUMNFIELDTYPE_BOOL),
CSVCOLUMNINFO("LifeTime", lifetime, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("ImpactDelay", impactdelay, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("FleshDamage", fleshdamage, CSVCOLUMNFIELDTYPE_NVEC),
@@ -871,8 +857,8 @@
CSVCOLUMNINFO("DamageRadius", damageradius, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("Shake", shake, CSVCOLUMNFIELDTYPE_NVEC),
CSVCOLUMNINFO("ShakeRadius", shakeradius, CSVCOLUMNFIELDTYPE_NVEC),
- //CSVCOLUMNINFO("IdleAnim", idleanim, CSVCOLUMNFIELDTYPE_CHARPOINTER),
- //CSVCOLUMNINFO("IdleFPS", idlefps, CSVCOLUMNFIELDTYPE_NVEC),
+ CSVCOLUMNINFO("IdleAnim", idleanim, CSVCOLUMNFIELDTYPE_CHARPOINTER),
+ CSVCOLUMNINFO("IdleFPS", idlefps, CSVCOLUMNFIELDTYPE_NVEC),
{NULL, 0, CSVCOLUMNFIELDTYPE_END}
};
@@ -952,10 +938,7 @@
switch(info->fieldtype)
{
case CSVCOLUMNFIELDTYPE_CHARPOINTER:
- if (token[0])
- String_Set(&fieldpointer->p, GS.memzone, token);
- else
- fieldpointer->p = NULL;
+ String_Set(&fieldpointer->p, GS.memzone, token);
break;
case CSVCOLUMNFIELDTYPE_NVEC:
fieldpointer->f = atof(token);
@@ -966,39 +949,6 @@
default:
break;
}
-#if 0
- case CSVCOLUMN_CodeName: String_Set(&eclass->codename, token);break;
- case CSVCOLUMN_EnglishName: String_Set(&eclass->codename, token);break;
- case CSVCOLUMN_Class: String_Set(&eclass->codename, token);break;
- case CSVCOLUMN_Model: String_Set(&eclass->codename, token);break;
- case CSVCOLUMN_Mass: eclass->mass = atof(token);break;
- case CSVCOLUMN_Health: eclass->health = atof(token);break;
- case CSVCOLUMN_Heal: eclass->heal = atof(token);break;
- case CSVCOLUMN_NoRemove: eclass->noremove = !String_ICompare(token, "TRUE");break;
- case CSVCOLUMN_I1Q: String_Set(&eclass->codename, token);break;
- case CSVCOLUMN_Projectile: String_Set(&eclass->projectilename, token);break;
- case CSVCOLUMN_SemiRefire: eclass->semirefire = atof(token);break;
- case CSVCOLUMN_AutoRefire: eclass->autorefire = atof(token);break;
- case CSVCOLUMN_Speed: eclass-> = atof(token);break;
- case CSVCOLUMN_Acceleration: eclass-> = atof(token);break;
- case CSVCOLUMN_TopSpeed: eclass-> = atof(token);break;
- case CSVCOLUMN_LifeTime: eclass-> = atof(token);break;
- case CSVCOLUMN_ImpactDelay: eclass-> = atof(token);break;
- case CSVCOLUMN_FleshDamage: eclass-> = atof(token);break;
- case CSVCOLUMN_ArmorDAmage: eclass-> = atof(token);break;
- case CSVCOLUMN_Force: eclass-> = atof(token);break;
- case CSVCOLUMN_damageRadius: eclass-> = atof(token);break;
- case CSVCOLUMN_Shake: eclass-> = atof(token);break;
- case CSVCOLUMN_ShakeRadius: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- case CSVCOLUMN_: eclass-> = atof(token);break;
- }
-#endif
column++;
}
if (tokentype == G_CSV_TOKENTYPE_EOF)
Modified: trunk/game/g_main.c
===================================================================
--- trunk/game/g_main.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_main.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -154,7 +154,7 @@
if (!Video_SetMode(Cvar_GetValue("vid_width")->ival, Cvar_GetValue("vid_height")->ival, 32, Cvar_GetValue("vid_fullscreen")->ival, true))
if (!Video.width || !Video_SetMode(Video.width, Video.height, Video.bpp, Video.fullscreen, Video.openglmode))
if (!Video_SetMode(640, 480, 32, false, true))
- if (!Video_SetMode(640, 480, 32, false, false))
+ //if (!Video_SetMode(640, 480, 32, false, false))
{
Console_Printf("Unable to open video!\n");
GS.quit = true;
@@ -200,6 +200,11 @@
GS.realtime = GS.oldrealtime = System_Time();
GS.protocolname = "DarkWar1";
+ Matrix4x4_CreateIdentity(&GS.identityposition.m);
+ Matrix4x4_CreateIdentity(&GS.identityposition.inversem);
+ VectorClear(GS.identityposition.velocity);
+ Vector4Set(GS.identityposition.spin, 1, 0, 0, 0);
+
Menu_Init();
G_InitCommands();
G_World_Init();
Modified: trunk/game/g_main.h
===================================================================
--- trunk/game/g_main.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_main.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -2,6 +2,15 @@
#ifndef G_MAIN_H
#define G_MAIN_H
+typedef struct G_Entity_Position
+{
+ matrix4x4_t m;
+ matrix4x4_t inversem;
+ Nvec3 velocity;
+ Nvec4 spin;
+}
+G_Entity_Position;
+
#include "game/g_network.h"
#include "collision.h"
@@ -205,6 +214,9 @@
NUint8 *server_networkresource_sent;
NUint32 client_networkresource_maxindices;
NUint32 *client_networkresource_remapindex;
+ // reference values for initializing structs
+ matrix4x4_t identitymatrix;
+ G_Entity_Position identityposition;
}
G_Static;
@@ -277,23 +289,14 @@
#define G_SCOPE_NETWORK_HEARABLE (1<<24)
#define G_SCOPE_AUDIO_SOUNDSOURCE (1<<25)
-typedef struct G_Entity_Field
-{
- struct G_Entity_Field *next;
- char *key;
- char *value;
-}
-G_Entity_Field;
-
// the protocol only supports up to 128
#define G_ENTITYCLASS_MAX 128
#define G_ENTITYCLASS_INVENTORY_MAX 6
typedef struct G_Entity_Class_InventoryEntry
{
- Nvec quantity;
- Nvec regen;
char *codename;
+ char *transformname;
}
G_Entity_Class_InventoryEntry;
@@ -331,7 +334,10 @@
Nvec health;
Nvec heal;
Nbool noremove;
+ Nvec respawn;
G_Entity_Class_InventoryEntry inventory[G_ENTITYCLASS_INVENTORY_MAX];
+ Nvec ammomax;
+ Nvec ammoregen;
char *projectilecodename;
Nvec semirefire;
Nvec autorefire;
@@ -349,6 +355,10 @@
Nvec airstopspeed;
Nvec hoverthrust;
Nvec hoveraltitude;
+ Nbool cloaking;
+ Nbool jumpflight;
+ Nbool crouchshield;
+ Nbool crouchturret;
Nvec lifetime;
Nvec impactdelay;
Nvec fleshdamage;
@@ -357,6 +367,8 @@
Nvec damageradius;
Nvec shake;
Nvec shakeradius;
+ char *idleanim;
+ Nvec idlefps;
}
G_Entity_Class;
@@ -414,6 +426,52 @@
#define G_ENTITY_CHILDREN 16
+typedef enum G_Entity_AnimationType
+{
+ G_ANIM_IDLE,
+ G_ANIM_FIRE1,
+ G_ANIM_FIRE2,
+ G_ANIM_RELOAD,
+ G_ANIM_THROW,
+ G_ANIM_GET,
+ G_ANIM_PUT,
+ G_ANIM_RUNFORWARD,
+ G_ANIM_RUNBACKWARD,
+ G_ANIM_RUNLEFT,
+ G_ANIM_RUNRIGHT,
+ G_ANIM_WALKFORWARD,
+ G_ANIM_WALKBACKWARD,
+ G_ANIM_WALKLEFT,
+ G_ANIM_WALKRIGHT,
+ G_ANIM_ROLLFORWARD,
+ G_ANIM_ROLLBACKWARD,
+ G_ANIM_ROLLLEFT,
+ G_ANIM_ROLLRIGHT,
+ G_ANIM_JUMP,
+ G_ANIM_FALL,
+ G_ANIM_LAND,
+ G_ANIM_DYING,
+ G_ANIM_DEAD,
+ G_ANIM_SIGNAL_FORWARD,
+ G_ANIM_SIGNAL_STOP,
+ G_ANIM_SIGNAL_RETREAT,
+ G_ANIM_SIGNAL_ATTACK,
+ G_ANIM_SIGNAL_DEFEND,
+ G_ANIM_SIGNAL_HOLDPOSITION,
+}
+G_Entity_AnimationType;
+
+typedef struct G_Entity_AnimationState
+{
+ // type of animation (for comparison purposes)
+ G_Entity_AnimationType type;
+ // time since animation started
+ float time;
+ // the ModelAnim resource being shownf
+ NUint32 resourceindex;
+}
+G_Entity_AnimationState;
+
typedef struct G_Entity
{
// class this entity uses
@@ -422,24 +480,29 @@
// owner of this entity (used by projectiles mainly)
struct G_Entity *owner;
struct G_Entity *children[G_ENTITY_CHILDREN];
+ struct G_Entity *attachment_entity;
+ NUint32 attachment_transformindex;
+ matrix4x4_t attachment_matrix;
G_Entity_Surface *surfacelist;
G_Entity_Sound sound;
+ G_Entity_AnimationState anim_head;
+ G_Entity_AnimationState anim_torso;
+ G_Entity_AnimationState anim_legs;
// if >= 0 this is the index in the G.client_networkentityindex array that
// contains a pointer to this entity
NSint32 networkindex;
// index of associated user if this is a player entity
NUint32 localuserindex;
+ // pressed buttons as of last Infantry_Frame call, causes weapons to fire
+ NUint32 buttons;
// TODO: rendering
// index of model this entity is using
NUint32 modelindex;
// set of skeletal transforms for rendering the model, or NULL for static
+ NUint32 numtransforms;
matrix4x4_t *transforms;
- // entity transform (skeletal is relative to this)
- matrix4x4_t matrix;
- // velocity (second order position)
- Nvec3 velocity;
- // axis and angle
- Nvec4 spinvelocity;
+ // entity transform (skeletal is relative to this) and velocity
+ G_Entity_Position position;
// builtin collision brush buffers (to avoid alloc/free)
Collision_Brush collisionbrush;
Collision_Point collisionbrushpoints[16];
@@ -470,7 +533,14 @@
Nvec quantity;
// fields (classname and origin and so on), only present in editing mode
// and during loading
- G_Entity_Field *fields;
+ NStringKeys keys;
+ // animation
+ G_Entity_AnimationState anim;
+ Nvec animframe;
+ // projectiles
+ Nvec lifetime;
+ // weapons
+ Nvec attackdelay;
}
G_Entity;
Modified: trunk/game/g_network.c
===================================================================
--- trunk/game/g_network.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_network.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -278,9 +278,9 @@
if (netconnection->entitypriority[i] < (G_NET_ENTITYPRIORITYLEVELS-1))
{
Nvec3 relativeorigin;
- relativeorigin[0] = G.entities[i].matrix.m[0][3] - netconnection->eyeorigin[0];
- relativeorigin[1] = G.entities[i].matrix.m[1][3] - netconnection->eyeorigin[1];
- relativeorigin[2] = G.entities[i].matrix.m[2][3] - netconnection->eyeorigin[2];
+ relativeorigin[0] = G.entities[i].position.m.m[0][3] - netconnection->eyeorigin[0];
+ relativeorigin[1] = G.entities[i].position.m.m[1][3] - netconnection->eyeorigin[1];
+ relativeorigin[2] = G.entities[i].position.m.m[2][3] - netconnection->eyeorigin[2];
newpriority = (int)(G_NET_ENTITYPRIORITYMAX - VectorLength(relativeorigin) * G_NET_ENTITYPRIORITYDISTANCESCALE);
newpriority = netconnection->entitypriority[i] + Max(G_NET_ENTITYPRIORITYMIN, newpriority);
netconnection->entitypriority[i] = (NUint8)Min(newpriority, G_NET_ENTITYPRIORITYLEVELS-1);
Modified: trunk/game/g_packetbuffer.c
===================================================================
--- trunk/game/g_packetbuffer.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_packetbuffer.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -194,56 +194,81 @@
// functions for more specialized data types
-void G_PacketBuffer_WriteMatrix(G_PacketBuffer *buf, matrix4x4_t *matrix, Nbool sendorigin, Nbool sendrotation, Nbool sendscale)
+void G_PacketBuffer_WritePosition(G_PacketBuffer *buf, G_Entity_Position *p, Nbool sendorigin, Nbool sendrotation, Nbool sendscale, Nbool sendvelocity, Nbool sendspin)
{
+ // location
if (sendorigin)
{
- G_PacketBuffer_WriteFloat(buf, matrix->m[0][3]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[1][3]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[2][3]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[0][3]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[1][3]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[2][3]);
}
// TODO: optimize rotation/scale sending, rotation can be sent as a 3
// component version of a normalized quat, scale can be sent as a float
if (sendrotation || sendscale)
{
- G_PacketBuffer_WriteFloat(buf, matrix->m[0][0]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[0][1]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[0][2]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[1][0]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[1][1]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[1][2]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[2][0]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[2][1]);
- G_PacketBuffer_WriteFloat(buf, matrix->m[2][2]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[0][0]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[1][0]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[2][0]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[0][1]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[1][1]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[2][1]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[0][2]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[1][2]);
+ G_PacketBuffer_WriteFloat(buf, p->m.m[2][2]);
}
+ // second order location (velocity)
+ if (sendvelocity)
+ {
+ G_PacketBuffer_WriteFloat(buf, p->velocity[0]);
+ G_PacketBuffer_WriteFloat(buf, p->velocity[1]);
+ G_PacketBuffer_WriteFloat(buf, p->velocity[2]);
+ }
+ // second order rotation (spin)
+ // this is a rodrigues vector (axis plus angle of rotation around it)
+ if (sendspin)
+ {
+ G_PacketBuffer_WriteFloat(buf, p->spin[0]);
+ G_PacketBuffer_WriteFloat(buf, p->spin[1]);
+ G_PacketBuffer_WriteFloat(buf, p->spin[2]);
+ G_PacketBuffer_WriteFloat(buf, p->spin[3]);
+ }
}
-void G_PacketBuffer_ReadMatrix(G_PacketBuffer *buf, matrix4x4_t *matrix, Nbool sendorigin, Nbool sendrotation, Nbool sendscale)
+void G_PacketBuffer_ReadPosition(G_PacketBuffer *buf, G_Entity_Position *p, Nbool sendorigin, Nbool sendrotation, Nbool sendscale, Nbool sendvelocity, Nbool sendspin)
{
+ *p = GS.identityposition;
if (sendorigin)
{
- matrix->m[0][3] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[1][3] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[2][3] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[0][3] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[1][3] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[2][3] = G_PacketBuffer_ReadFloat(buf);
}
if (sendrotation || sendscale)
{
- matrix->m[0][0] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[0][1] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[0][2] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[1][0] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[1][1] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[1][2] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[2][0] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[2][1] = G_PacketBuffer_ReadFloat(buf);
- matrix->m[2][2] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[0][0] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[0][1] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[0][2] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[1][0] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[1][1] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[1][2] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[2][0] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[2][1] = G_PacketBuffer_ReadFloat(buf);
+ p->m.m[2][2] = G_PacketBuffer_ReadFloat(buf);
}
- // LordHavoc: for a good time, comment out these lines; it took me a long
- // time to figure out the resulting rendering bug.
- matrix->m[3][0] = 0;
- matrix->m[3][1] = 0;
- matrix->m[3][2] = 0;
- matrix->m[3][3] = 1;
+ if (sendvelocity)
+ {
+ p->velocity[0] = G_PacketBuffer_ReadFloat(buf);
+ p->velocity[1] = G_PacketBuffer_ReadFloat(buf);
+ p->velocity[2] = G_PacketBuffer_ReadFloat(buf);
+ }
+ if (sendspin)
+ {
+ p->spin[0] = G_PacketBuffer_ReadFloat(buf);
+ p->spin[1] = G_PacketBuffer_ReadFloat(buf);
+ p->spin[2] = G_PacketBuffer_ReadFloat(buf);
+ p->spin[3] = G_PacketBuffer_ReadFloat(buf);
+ }
}
void G_PacketBuffer_WriteColorVector16(G_PacketBuffer *buf, Nvec3 color)
@@ -322,3 +347,18 @@
return G_World_ResourceIndex_FromNetwork(G_PacketBuffer_Read32(buf));
}
+void G_PacketBuffer_WriteEntityAsIndex(G_PacketBuffer *buf, G_Entity *entity)
+{
+ G_PacketBuffer_Write16(buf, entity - G.entities);
+}
+
+G_Entity *G_PacketBuffer_ReadEntityAsIndex(G_PacketBuffer *buf)
+{
+ NUint32 index;
+ index = G_PacketBuffer_Read16(buf);
+ if (index >= G_MAX_ENTITIES)
+ return NULL;
+ if (G.client_networkentityindex[index] < 0)
+ return NULL;
+ return G.entities + G.client_networkentityindex[index];
+}
Modified: trunk/game/g_packetbuffer.h
===================================================================
--- trunk/game/g_packetbuffer.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_packetbuffer.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -51,8 +51,10 @@
Nsize G_PacketBuffer_ReadBytes(G_PacketBuffer *buf, NUint8 *buffer, Nsize buffersize);
// functions for more specialized data types:
-void G_PacketBuffer_WriteMatrix(G_PacketBuffer *buf, matrix4x4_t *matrix, Nbool sendorigin, Nbool sendrotation, Nbool sendscale);
-void G_PacketBuffer_ReadMatrix(G_PacketBuffer *buf, matrix4x4_t *matrix, Nbool sendorigin, Nbool sendrotation, Nbool sendscale);
+struct G_Entity_Position;
+struct G_Entity;
+void G_PacketBuffer_WritePosition(G_PacketBuffer *buf, struct G_Entity_Position *p, Nbool sendorigin, Nbool sendrotation, Nbool sendscale, Nbool sendvelocity, Nbool sendspin);
+void G_PacketBuffer_ReadPosition(G_PacketBuffer *buf, struct G_Entity_Position *p, Nbool sendorigin, Nbool sendrotation, Nbool sendscale, Nbool sendvelocity, Nbool sendspin);
void G_PacketBuffer_WriteColorVector16(G_PacketBuffer *buf, Nvec3 color);
void G_PacketBuffer_ReadColorVector16(G_PacketBuffer *buf, Nvec3 color);
void G_PacketBuffer_WriteClamped8(G_PacketBuffer *buf, Nvec f, Nvec scale);
@@ -61,6 +63,8 @@
void G_PacketBuffer_ReadAngles16(G_PacketBuffer *buf, Nvec3 angles);
void G_PacketBuffer_WriteBool(G_PacketBuffer *buf, NUint32 i);
Nbool G_PacketBuffer_ReadBool(G_PacketBuffer *buf);
+void G_PacketBuffer_WriteEntityAsIndex(G_PacketBuffer *buf, struct G_Entity *entity);
+struct G_Entity *G_PacketBuffer_ReadEntityAsIndex(G_PacketBuffer *buf);
// nocache versions send the actual name string (type has to be known by the reader)
void G_PacketBuffer_WriteResourceIndex_NoCache(G_PacketBuffer *buf, NUint32 i);
NUint32 G_PacketBuffer_ReadResourceIndex_NoCache(G_PacketBuffer *buf, NUint32 type);
Modified: trunk/game/g_render.c
===================================================================
--- trunk/game/g_render.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_render.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -29,7 +29,7 @@
// TODO: verify the resource type is RESOURCETYPE_MODEL
model = Resource_GetData(entity->modelindex);
if (model)
- R_SetEntity(&entity->matrix, entity->cullradius, entity->modelindex);
+ R_SetEntity(&entity->position.m, entity->cullradius, entity->modelindex);
}
if (!model)
continue;
@@ -64,7 +64,7 @@
if (currententity != entity)
{
currententity = entity;
- R_SetEntity(&entity->matrix, entity->cullradius, entity->modelindex);
+ R_SetEntity(&entity->position.m, entity->cullradius, entity->modelindex);
}
mesh = model->meshes + surface->meshindex;
material = Resource_GetData(mesh->resource_material);
@@ -89,7 +89,7 @@
mode = R_DRAWMODE_LIT_LIGHTING;
R_SetDrawMode(R_DRAWMODE_LIT_LIGHTING);
}
- R_SetLight(&light->matrix, light->lightcolor, light->lightcubemap, light->lightambientintensity, light->lightdiffuseintensity, light->lightspecularintensity);
+ R_SetLight(&light->position.m, light->lightcolor, light->lightcubemap, light->lightambientintensity, light->lightdiffuseintensity, light->lightspecularintensity);
R_DrawMesh(mesh->resource_material, surface->meshindex, entity->transforms);
}
}
@@ -389,11 +389,11 @@
light = G.drawview_lights[lnum];
// tell the renderer to prepare for light rendering
- R_SetLight(&light->matrix, light->lightcolor, light->lightcubemap, light->lightambientintensity, light->lightdiffuseintensity, light->lightspecularintensity);
+ R_SetLight(&light->position.m, light->lightcolor, light->lightcubemap, light->lightambientintensity, light->lightdiffuseintensity, light->lightspecularintensity);
// find all surfaces visible to the light
- Matrix4x4_OriginFromMatrix(&light->matrix, lightorigin);
- lightradius = Matrix4x4_ScaleFromMatrix(&light->matrix);
+ Matrix4x4_OriginFromMatrix(&light->position.m, lightorigin);
+ lightradius = Matrix4x4_ScaleFromMatrix(&light->position.m);
G_Scope_VisibleSurfacesAndLights(G_SCOPE_RENDER_OPAQUE, lightorigin, lightradius, G_DRAWVIEW_SURFACES, G.drawview_light_surfaces, &G.drawview_light_numsurfaces, 0, NULL, NULL, false);
// make lists by type from the visible surfaces
Modified: trunk/game/g_world.c
===================================================================
--- trunk/game/g_world.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/game/g_world.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -225,13 +225,18 @@
{
NUint32 j;
Util_ParseC_Thread thread;
+ NStringKeys keys;
+ G_Entity *entity;
+ const G_Entity_Class *eclass;
char *key[2];
- G_Entity *entity;
+ Nvec3 origin, angles;
+ Nvec scale;
+ G_Entity_Position position;
+ Util_ParseC_SetUpThread(&thread, filedata, filesize);
+ StringKeys_Init(&keys, GS.memzone, 65536);
key[0] = NULL;
key[1] = NULL;
-
- Util_ParseC_SetUpThread(&thread, filedata, filesize);
while (thread.type != UTIL_PARSEC_TOKENTYPE_EOF)
{
if (!Util_ParseC_MatchName(&thread, "{"))
@@ -239,7 +244,12 @@
Console_Printf("G_SpawnFromEntityFile: expected {\n");
break;
}
- entity = G_Entity_New(NULL, G_EntityClass_ByNumber(0));
+ StringKeys_Empty(&keys);
+ position = GS.identityposition;
+ eclass = NULL;
+ VectorClear(origin);
+ VectorClear(angles);
+ scale = 1;
for (;;)
{
for (j = 0;j < 2;j++)
@@ -265,21 +275,56 @@
}
if (j < 2)
break;
- G_Entity_SetField(entity, key[0], key[1]);
+ if (!String_Compare(key[0], "classname"))
+ {
+ if (eclass)
+ Console_Printf("G_SpawnFromEntityFile: entity with multiple classnames\n");
+ eclass = G_EntityClass_ByName(key[1]);
+ }
+ else if (!String_Compare(key[0], "origin"))
+ String_ToVector(key[1], origin, 3);
+ else if (!String_Compare(key[0], "angles"))
+ String_ToVector(key[1], angles, 3);
+ else if (!String_Compare(key[0], "scale"))
+ scale = String_ToDouble(key[1]);
+ else if (!String_Compare(key[0], "velocity"))
+ String_ToVector(key[1], position.velocity, 3);
+ else if (!String_Compare(key[0], "spin"))
+ String_ToVector(key[1], position.spin, 4);
+ StringKeys_SetKey(&keys, GS.memzone, key[0], key[1]);
}
+ if (eclass)
+ {
+ const char *s;
+ Matrix4x4_CreateFromQuakeEntity(&position.m, origin[0], origin[1], origin[2], angles[0], angles[1], angles[2], scale);
+ // TODO: parse keys here?
+ entity = G_Entity_New(NULL, eclass, &position);
+ // set up the most general fields to save code in spawn functions
+ String_ToVector(StringKeys_GetValue(&keys, "color"), entity->lightcolor, 3);
+ if ((s = StringKeys_GetValue(&keys, "cubemap")))
+ entity->lightcubemap = Resource_IndexForName(s, RESOURCETYPE_TEXTURE, 0, 0);
+ if ((s = StringKeys_GetValue(&keys, "model")))
+ G_Entity_SetModel(entity, s);
+ // only keep keys if in editing mode
+ if (G.editing)
+ StringKeys_Clone(&entity->keys, GS.memzone, &keys);
+ }
+ else
+ Console_Printf("G_SpawnFromEntityFile: entity with no classname\n");
}
- Util_ParseC_CleanUpThread(&thread);
String_Free(&key[0]);
String_Free(&key[1]);
+ StringKeys_FreeKeys(&keys);
+ Util_ParseC_CleanUpThread(&thread);
}
void G_World_SaveEntities(const char *filename)
{
- NUint32 i, j;
+ NUint32 i, j, keyindex;
Nsize filesize;
G_Entity *entity;
- G_Entity_Field *field;
char *filedata;
+ const char *key, *value;
if (!G.editing)
{
// we can't save because the entity fields were destroyed at load, and
@@ -294,15 +339,16 @@
{
// TODO: optimize this to buffer a bit rather than using String_Append?
String_Append(&filedata, GS.memzone, "{\n");
- for (field = entity->fields;field;field = field->next)
+ keyindex = 0;
+ for (keyindex = 0;StringKeys_GetByNumber(&entity->keys, keyindex, &key, &value);keyindex++)
{
// FIXME: field->key is pretty safe but key->value may contain
// control characters like \n, these need to be converted to
// escape sequences.
String_Append(&filedata, GS.memzone, "\t\"");
- String_Append(&filedata, GS.memzone, field->key);
+ String_Append(&filedata, GS.memzone, key);
String_Append(&filedata, GS.memzone, "\" \"");
- String_Append(&filedata, GS.memzone, field->value);
+ String_Append(&filedata, GS.memzone, value);
String_Append(&filedata, GS.memzone, "\"\n");
}
String_Append(&filedata, GS.memzone, "}\n");
@@ -336,8 +382,8 @@
Mem_Free(&filedata);
for (i = 0;i < G_MAX_ENTITIES;i++)
- if (G.entities[i].eclass && G.entities[i].fields)
- G_Entity_SpawnFromFields(G.entities + i);
+ if (G.entities[i].eclass)
+ G_Entity_Spawn(G.entities + i);
// TODO: add team entities
// if no teams were defined by entities, set up default teams
@@ -438,7 +484,7 @@
G.time += G.frametime;
// execute entity think code
for (i = 0, entity = G.entities;i < G.numentities;i++, entity++)
- if (entity->eclass && entity->eclass->codeclass && entity->eclass->codeclass->framecallback)
+ if (entity->eclass && entity->eclass->codeclass->framecallback)
entity->eclass->codeclass->framecallback(entity);
// TODO: call physics
#if 0
@@ -459,18 +505,19 @@
{
G_Entity *player;
G_Entity *spot;
+ G_Entity_Position position;
+ // TODO: better spawn point selection
+ spot = G_Entity_Find_CodeName(NULL, "spawninfantry");
+ if (spot)
+ position = spot->position;
+ else
+ position = GS.identityposition;
// set up player entity for this user
- player = G_Entity_New(NULL, G_EntityClass_ByName("infantry"));
+ player = G_Entity_New(NULL, G_EntityClass_ByName("infantry"), &position);
player->localuserindex = user - GS.users;
G.users[player->localuserindex].teamindex = 1;
G.users[player->localuserindex].score = 0;
//G.users[player->localuserindex].entityindex = player - G.entities;
- // TODO: better spawn point selection
- spot = G_Entity_Find_CodeName(NULL, "spawninfantry");
- if (spot)
- player->matrix = spot->matrix;
- else
- Matrix4x4_CreateIdentity(&player->matrix);
G_Entity_Spawn(player);
}
@@ -546,8 +593,8 @@
continue;
if (e == trace->moveentity)
continue;
- Matrix4x4_Invert_Simple(&imatrix, &e->matrix);
- Collision_Trace_Begin(&collisiontrace, &e->matrix, &imatrix, &startbrush, &endbrush, 1.0/32.0);
+ Matrix4x4_Invert_Simple(&imatrix, &e->position.m);
+ Collision_Trace_Begin(&collisiontrace, &e->position.m, &imatrix, &startbrush, &endbrush, 1.0/32.0);
if (e->collisionbrush.numpoints)
Collision_Trace_CheckBrushes(&collisiontrace, 1, &e->collisionbrush, &e->collisionbrush);
else if (e->surfacelist)
Modified: trunk/mathlib.h
===================================================================
--- trunk/mathlib.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/mathlib.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -16,31 +16,69 @@
#define RAD2DEG(a) ((a) * (180.0 / M_PI))
#define VectorNegate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]),(b)[2]=-((a)[2]))
+#define Vector2Negate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]))
+#define Vector4Negate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]),(b)[2]=-((a)[2]),(b)[3]=-((a)[3]))
#define VectorSet(a,b,c,d) ((a)[0]=(b),(a)[1]=(c),(a)[2]=(d))
+#define Vector2Set(a,b,c) ((a)[0]=(b),(a)[1]=(c))
+#define Vector4Set(a,b,c,d,e) ((a)[0]=(b),(a)[1]=(c),(a)[2]=(d),(a)[3]=(e))
#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
-#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
-#define DotProduct4(a,b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2] + (a)[3] * (b)[3])
+#define Vector2Clear(a) ((a)[0]=(a)[1]=0)
+#define Vector4Clear(a) ((a)[0]=(a)[1]=(a)[2]=(a)[3]=0)
#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+#define Vector2Subtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1])
+#define Vector4Subtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+#define Vector2Add(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1])
+#define Vector4Add(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[2]=(a)[3]+(b)[3])
#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+#define Vector2Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
+#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define VectorMultiply(a,b,c) ((c)[0]=(a)[0]*(b)[0],(c)[1]=(a)[1]*(b)[1],(c)[2]=(a)[2]*(b)[2])
-#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-#define VectorNormalize(v) do{float ilength = (float) sqrt(DotProduct(v,v));if (ilength) {ilength = 1.0f / ilength;VectorScale(v, ilength, v);}}while(0)
-#define VectorNormalizeDouble(v) do{double ilength = sqrt(DotProduct(v,v));if (ilength) {ilength = 1.0 / ilength;VectorScale(v, ilength, v);}}while(0)
+#define Vector2Multiply(a,b,c) ((c)[0]=(a)[0]*(b)[0],(c)[1]=(a)[1]*(b)[1])
+#define Vector4Multiply(a,b,c) ((c)[0]=(a)[0]*(b)[0],(c)[1]=(a)[1]*(b)[1],(c)[2]=(a)[2]*(b)[2],(c)[3]=(a)[3]*(b)[3])
+#define VectorNormalize(v) do{double ilength = sqrt(DotProduct(v,v));if (ilength) {ilength = 1.0 / ilength;VectorScale(v, ilength, v);}}while(0)
+#define Vector2Normalize(v) do{double ilength = sqrt(DotProduct2(v,v));if (ilength) {ilength = 1.0 / ilength;Vector2Scale(v, ilength, v);}}while(0)
+#define Vector4Normalize(v) do{double ilength = sqrt(DotProduct4(v,v));if (ilength) {ilength = 1.0 / ilength;Vector4Scale(v, ilength, v);}}while(0)
#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
+#define Vector2Distance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]))
+#define Vector4Distance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]) + ((a)[3] - (b)[3]) * ((a)[3] - (b)[3]))
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
-#define VectorLength(a) (sqrt(DotProduct(a, a)))
+#define Vector2Distance(a, b) (sqrt(Vector2Distance2(a,b)))
+#define Vector4Distance(a, b) (sqrt(Vector4Distance2(a,b)))
#define VectorLength2(a) (DotProduct(a, a))
+#define Vector2Length2(a) (DotProduct2(a, a))
+#define Vector4Length2(a) (DotProduct4(a, a))
+#define VectorLength(a) (sqrt(VectorLength2(a)))
+#define Vector2Length(a) (sqrt(Vector2Length2(a)))
+#define Vector4Length(a) (sqrt(Vector4Length2(a)))
#define VectorScale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale),(out)[2] = (in)[2] * (scale))
+#define Vector2Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale))
+#define Vector4Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale),(out)[2] = (in)[2] * (scale),(out)[3] = (in)[3] * (scale))
#define VectorCompare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1])&&((a)[2]==(b)[2]))
+#define Vector2Compare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1]))
+#define Vector4Compare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1])&&((a)[2]==(b)[2])&&((a)[3]==(b)[3]))
#define VectorMA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1],(c)[2] = (a)[2] + (scale) * (b)[2])
+#define Vector2MA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1])
+#define Vector4MA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1],(c)[2] = (a)[2] + (scale) * (b)[2],(c)[3] = (a)[3] + (scale) * (b)[3])
#define VectorRandom(v) do{(v)[0] = Random(-1, 1);(v)[1] = Random(-1, 1);(v)[2] = Random(-1, 1);}while(DotProduct(v, v) > 1)
+#define Vector2Random(v) do{(v)[0] = Random(-1, 1);(v)[1] = Random(-1, 1);}while(DotProduct2(v, v) > 1)
+#define Vector4Random(v) do{(v)[0] = Random(-1, 1);(v)[1] = Random(-1, 1);(v)[2] = Random(-1, 1);(v)[3] = Random(-1, 1);}while(DotProduct4(v, v) > 1)
#define VectorLerp(v1,lerp,v2,c) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]), (c)[2] = (v1)[2] + (lerp) * ((v2)[2] - (v1)[2]))
+#define Vector2Lerp(v1,lerp,v2,c) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]))
+#define Vector4Lerp(v1,lerp,v2,c) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]), (c)[2] = (v1)[2] + (lerp) * ((v2)[2] - (v1)[2]), (c)[3] = (v1)[3] + (lerp) * ((v2)[3] - (v1)[3]))
+#define VectorReflect(a,r,b,c) do{Nvec d;d = DotProduct((a), (b)) * -(1.0 + (r));VectorMA((a), (d), (b), (c));}while(0)
+#define Vector2Reflect(a,r,b,c) do{Nvec d;d = DotProduct2((a), (b)) * -(1.0 + (r));Vector2MA((a), (d), (b), (c));}while(0)
+
+#define DotProduct(a,b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2])
+#define DotProduct2(a,b) ((a)[0] * (b)[0] + (a)[1] * (b)[1])
+#define DotProduct4(a,b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2] + (a)[3] * (b)[3])
+#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
#define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2])
+#define BoxesOverlap2(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1])
#define SpheresOverlap(a,b,c,d) (VectorDistance2(a,c) < (b*b+d*d))
+#define CirclesOverlap(a,b,c,d) (Vector2Distance2(a,c) < (b*b+d*d))
#define TriangleNormal(a,b,c,n) ((n)[0] = ((a)[2] - (b)[2]) * ((c)[1] - (b)[1]) - ((a)[1] - (b)[1]) * ((c)[2] - (b)[2]), (n)[1] = ((a)[0] - (b)[0]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[0] - (b)[0]), (n)[2] = ((a)[1] - (b)[1]) * ((c)[0] - (b)[0]) - ((a)[0] - (b)[0]) * ((c)[1] - (b)[1]))
#define PointInfrontOfTriangle(p,a,b,c) (((p)[0] - (a)[0]) * (((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1])) + ((p)[1] - (a)[1]) * (((a)[2] - (b)[2]) * ((c)[0] - (b)[0]) - ((a)[0] - (b)[0]) * ((c)[2] - (b)[2])) + ((p)[2] - (a)[2]) * (((a)[0] - (b)[0]) * ((c)[1] - (b)[1]) - ((a)[1] - (b)[1]) * ((c)[0] - (b)[0])) > 0)
-#define VectorReflect(a,r,b,c) do{Nvec d;d = DotProduct((a), (b)) * -(1.0 + (r));VectorMA((a), (d), (b), (c));}while(0)
// conversion of a quaternion to 3 components by making it canonical (there are two equivilant representations of any quaternion depending on the sign of w, negative or positive w can be eliminated by negating xyz, thus reducing a normalized quaternion to xyz with an easily calculated w)
#define Quat4ToQuat3(a,b) ((a)[3] > 0 ? VectorNegate((a),(b)) : VectorCopy((a),(b)))
Modified: trunk/model.c
===================================================================
--- trunk/model.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/model.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -212,18 +212,6 @@
}
Model_MD5_Weight;
-// LordHavoc: I got this code from:
-//http://www.doom3world.org/phpbb2/viewtopic.php?t=2884
-static void Model_Doom3Joint6ToMatrix(double *b, matrix4x4_t *m)
-{
- double x = b[3], y = b[4], z = b[5], w = 1.0 - DotProduct(b + 3, b + 3);
- w = w > 0.0 ? -sqrt(w) : 0.0;
- m->m[0][0]= 1-2*((y*y)+(z*z)) ;m->m[0][1]= 2*((x*y)-(z*w)) ;m->m[0][2]= 2*((x*z)+(y*w)) ;m->m[0][3]=b[0];
- m->m[1][0]= 2*((x*y)+(z*w)) ;m->m[1][1]= 1-2*((x*x)+(z*z)) ;m->m[1][2]= 2*((y*z)-(x*w)) ;m->m[1][3]=b[1];
- m->m[2][0]= 2*((x*z)-(y*w)) ;m->m[2][1]= 2*((y*z)+(x*w)) ;m->m[2][2]= 1-2*((x*x)+(y*y)) ;m->m[2][3]=b[2];
- m->m[3][0]= 0 ;m->m[3][1]= 0 ;m->m[3][2]= 0 ;m->m[3][3]= 1;
-}
-
void Model_Load(ResourceEntry *r)
{
Util_ParseC_Thread thread;
@@ -296,6 +284,7 @@
model->transformnames = Mem_Alloc(r->memzone, model->numtransforms * sizeof(*model->transformnames));
model->transformradius = Mem_Alloc(r->memzone, model->numtransforms * sizeof(*model->transformradius));
model->basetransforms = Mem_Alloc(r->memzone, model->numtransforms * sizeof(*model->basetransforms));
+ model->baseinversetransforms = Mem_Alloc(r->memzone, model->numtransforms * sizeof(*model->baseinversetransforms));
}
//numMeshes 1
else if (Util_ParseC_MatchKeyword(&thread, "numMeshes"))
@@ -334,7 +323,8 @@
LoadValue(joint6[4], "(joint 4)");
LoadValue(joint6[5], "(joint 5)");
ExpectKeyword(")", "after second joint data list");
- Model_Doom3Joint6ToMatrix(joint6, &model->basetransforms[jointnum]);
+ Matrix4x4_CreateFromDoom3Joint(&model->basetransforms[jointnum], joint6[0], joint6[1], joint6[2], joint6[3], joint6[4], joint6[5]);
+ Matrix4x4_Invert_Simple(&model->baseinversetransforms[jointnum], &model->basetransforms[jointnum]);
if (parent >= (NSint32)jointnum)
{
Console_Printf("Model_Load: joint.parent (%i) >= joint (%i)\n", parent, jointnum);
@@ -343,7 +333,7 @@
}
if (jointnum != model->numtransforms)
{
- Console_Printf("Model_Load: final jointnum (%i) != numjuoints (%i)\n", jointnum, model->numtransforms);
+ Console_Printf("Model_Load: final jointnum (%i) != numJoints (%i)\n", jointnum, model->numtransforms);
Abort();
}
}
@@ -814,6 +804,19 @@
}
}
+NSint32 Model_GetTransformNumberForName(NUint32 modelresource, const char *name)
+{
+ NUint32 i;
+ Model *model;
+ model = Resource_GetData(modelresource);
+ if (!model)
+ return -1; // no model
+ for (i = 0;i < model->numtransforms;i++)
+ if (!String_Compare(model->transformnames[i], name))
+ return i;
+ return -1;
+}
+
/*
// TODO: data hiding or not?
Modified: trunk/model.h
===================================================================
--- trunk/model.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/model.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -84,6 +84,7 @@
char **transformnames;
float *transformradius;
matrix4x4_t *basetransforms;
+ matrix4x4_t *baseinversetransforms;
Nvec3 basecullmins;
Nvec3 basecullmaxs;
@@ -98,6 +99,7 @@
void Model_GetVertices(Model_Mesh *mesh, const matrix4x4_t *transforms, float *outvertex3f, float *outsvector3f, float *outtvector3f, float *outnormal3f, float *outplane4f);
void Model_GetCullBox(NUint32 modelresource, const matrix4x4_t *transforms, Nvec3 cullmins, Nvec3 cullmaxs);
void Model_GetMeshCullBox(NUint32 modelresource, NUint32 meshindex, const matrix4x4_t *transforms, Nvec3 cullmins, Nvec3 cullmaxs);
+NSint32 Model_GetTransformNumberForName(NUint32 modelresource, const char *name);
#endif
Added: trunk/modelanim.c
===================================================================
--- trunk/modelanim.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/modelanim.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -0,0 +1,352 @@
+
+#include "ncommon.h"
+#include "model.h"
+#include "modelanim.h"
+#include "util.h"
+
+/* example clips of an MD5 anim
+MD5Version 10
+commandline ""
+numFrames 21
+numJoints 3
+frameRate 30
+numAnimatedComponents 18
+hierarchy {
+ "root" -1 63 0 //
+ "weapon_link" 0 63 6 // root ( Tx Ty Tz Qx Qy Qz )
+ "weapon_main" 1 63 12 // weapon_link ( Tx Ty Tz Qx Qy Qz )
+}
+bounds {
+ ( -1.145777 -2.429096 -13.948964 ) ( 19.801897 4.962530 -5.251172 )
+ ( -0.687599 -2.425639 -13.722960 ) ( 20.277922 5.083089 -4.994154 )
+...
+}
+baseframe {
+ ( 0.000000 0.000000 0.000000 ) ( -0.707107 0.000000 -0.000000 )
+ ( 0.000000 0.000000 -1.200000 ) ( 0.375011 0.599472 0.375011 )
+ ( -0.000000 0.000000 -12.343824 ) ( -0.681099 -0.000000 -0.000000 )
+}
+frame 0 {
+ 0.000000 0.000000 0.000000 -0.707107 0.000000 -0.000000
+ 0.000000 0.000000 -1.200000 0.375011 0.599472 0.375011
+ -0.000000 0.000000 -12.343824 -0.681099 -0.000000 -0.000000
+}
+...
+*/
+
+void ModelAnim_Load(ResourceEntry *r)
+{
+ Util_ParseC_Thread thread;
+ NUint32 meshnum, version;
+ Nbool error;
+ Nsize filesize;
+ ModelAnim *modelanim;
+ char *filedata;
+
+ modelanim = Mem_Alloc(r->memzone, sizeof(ModelAnim));
+
+ filedata = File_LoadFile(r->name, &filesize);
+ if (!filedata)
+ return;
+
+ Util_ParseC_SetUpThread(&thread, filedata, filesize);
+
+#define Abort() { error = true; break; }
+#define LoadValue(var, errstr) if (thread.type != UTIL_PARSEC_TOKENTYPE_VALUE) { \
+ Console_Printf("ModelAnim_Load: Expected value " errstr "\n"); Abort(); \
+ } else \
+ (var) = thread.value, Util_ParseC_Lex(&thread)
+
+#define LoadInt(var, errstr) if (thread.type != UTIL_PARSEC_TOKENTYPE_VALUE) { \
+ Console_Printf("ModelAnim_Load: Expected integer " errstr "\n"); Abort(); \
+ } else \
+ (var) = thread.value, Util_ParseC_Lex(&thread)
+
+#define LoadString(var, errstr) if (thread.type != UTIL_PARSEC_TOKENTYPE_STRING) { \
+ Console_Printf("ModelAnim_Load: Expected string " errstr "\n"); Abort(); \
+ } else \
+ String_Set( &(var), r->memzone, thread.token), Util_ParseC_Lex(&thread)
+
+#define ExpectKeyword(str, errstr) if (!Util_ParseC_MatchName(&thread, (str))) { \
+ Console_Printf("ModelAnim_Load: Expected '" str "' " errstr "\n"); Abort(); }
+
+ version = 0;
+ meshnum = 0;
+ error = false;
+
+ while (!error && thread.type != UTIL_PARSEC_TOKENTYPE_EOF)
+ {
+ //MD5Version 10
+ if (Util_ParseC_MatchKeyword(&thread, "MD5Version"))
+ {
+ LoadInt(version, "after 'MD5Version'");
+ if (version != 10)
+ {
+ Console_Printf("ModelAnim_Load: MD5Version %i not supported\n", version);
+ Abort();
+ }
+ }
+ //commandline ""
+ else if (Util_ParseC_MatchKeyword(&thread, "commandline"))
+ {
+ Util_ParseC_Lex(&thread);
+ }
+ //numFrames 21
+ else if (Util_ParseC_MatchKeyword(&thread, "numFrames"))
+ {
+ LoadInt(modelanim->numframes, "after 'numFrames'");
+ if (modelanim->numframes < 1)
+ {
+ Console_Printf("ModelAnim_Load: numFrames %i < 1\n", modelanim->numframes);
+ Abort();
+ }
+ }
+ //numJoints 3
+ else if (Util_ParseC_MatchKeyword(&thread, "numJoints"))
+ {
+ LoadInt(modelanim->numtransforms, "after 'numJoints'");
+ if (modelanim->numtransforms < 1)
+ {
+ Console_Printf("ModelAnim_Load: numJoints %i < 1\n", modelanim->numtransforms);
+ Abort();
+ }
+ }
+ //frameRate 30
+ else if (Util_ParseC_MatchKeyword(&thread, "frameRate"))
+ {
+ LoadValue(modelanim->framerate, "after 'frameRate'");
+ if (modelanim->framerate <= 0)
+ {
+ Console_Printf("ModelAnim_Load: frameRate %f <= 0\n", modelanim->framerate);
+ Abort();
+ }
+ }
+ //numAnimatedComponents 18
+ else if (Util_ParseC_MatchKeyword(&thread, "numAnimatedComponents"))
+ {
+ LoadInt(modelanim->numvaluesperframe, "after 'numAnimatedComponents'");
+ if (modelanim->numvaluesperframe < 0)
+ {
+ Console_Printf("ModelAnim_Load: numAnimatedComponents %i < 0\n", modelanim->numvaluesperframe);
+ Abort();
+ }
+ if (modelanim->numvaluesperframe > modelanim->numtransforms * 6)
+ {
+ Console_Printf("ModelAnim_Load: numAnimatedComponents %i > numJoints * 6\n", modelanim->numvaluesperframe);
+ Abort();
+ }
+ }
+ //hierarchy {
+ else if (Util_ParseC_MatchKeyword(&thread, "hierarchy"))
+ {
+ NUint32 jointnum;
+ ExpectKeyword("{", "after 'hierarchy'");
+ modelanim->transforminfo = Mem_Alloc(r->memzone, modelanim->numtransforms * sizeof(*modelanim->transforminfo));
+ for (jointnum = 0; !Util_ParseC_MatchKeyword(&thread, "}");jointnum++)
+ {
+ NSint32 parent;
+ NUint32 componentflags;
+ NUint32 numcomponents;
+ NUint32 firstcomponent;
+ NUint32 componentindex;
+ // "weapon_link" 0 63 6 // root ( Tx Ty Tz Qx Qy Qz )
+ LoadString(modelanim->transforminfo[jointnum].name, "for joint name");
+ LoadInt(parent, "as parent");
+ LoadInt(componentflags, "component flags");
+ LoadInt(firstcomponent, "first component index");
+ if (parent >= (NSint32)jointnum)
+ {
+ Console_Printf("ModelAnim_Load: joint.parent (%i) >= joint (%i)\n", parent, jointnum);
+ Abort();
+ }
+ if (componentflags & ~63)
+ {
+ Console_Printf("ModelAnim_Load: joint[%i].componentflags < 0 || componentflags > 63\n", jointnum);
+ Abort();
+ }
+ numcomponents = 0;
+ for (componentindex = 0;componentindex < 6;componentindex++)
+ if (componentflags & (1<<componentindex))
+ numcomponents++;
+ if (firstcomponent + numcomponents > modelanim->numvaluesperframe)
+ {
+ Console_Printf("ModelAnim_Load: joint[%i].firstcomponent < 0 || firstcomponent + numcomponents > numAnimatedComponents\n", jointnum);
+ Abort();
+ }
+ modelanim->transforminfo[jointnum].parentindex = parent;
+ modelanim->transforminfo[jointnum].valueflags = componentflags;
+ modelanim->transforminfo[jointnum].firstvalue = firstcomponent;
+ modelanim->transforminfo[jointnum].numvalues = numcomponents;
+ }
+ if (jointnum != modelanim->numtransforms)
+ {
+ Console_Printf("ModelAnim_Load: final jointnum (%i) != numJoints (%i)\n", jointnum, modelanim->numtransforms);
+ Abort();
+ }
+ }
+ //bounds {
+ else if (Util_ParseC_MatchKeyword(&thread, "bounds"))
+ {
+ NUint32 framenum;
+ ExpectKeyword("{", "after 'bounds'");
+ for (framenum = 0; !Util_ParseC_MatchKeyword(&thread, "}");framenum++)
+ {
+ Nvec3 mins, maxs;
+ // ( -1.145777 -2.429096 -13.948964 ) ( 19.801897 4.962530 -5.251172 )
+ ExpectKeyword("(", "before minimum corner of frame box");
+ LoadValue(mins[0], "(mins[0])");
+ LoadValue(mins[1], "(mins[1])");
+ LoadValue(mins[2], "(mins[2])");
+ ExpectKeyword(")", "after minimum corner of frame box");
+ ExpectKeyword("(", "before maximum corner of frame box");
+ LoadValue(maxs[0], "(maxs[0])");
+ LoadValue(maxs[1], "(maxs[1])");
+ LoadValue(maxs[2], "(maxs[2])");
+ ExpectKeyword(")", "after maximum corner of frame box");
+ }
+ if (framenum != modelanim->numframes)
+ {
+ Console_Printf("ModelAnim_Load: final framenum (%i) != numFrames (%i)\n", framenum, modelanim->numframes);
+ Abort();
+ }
+ }
+ //baseframe {
+ else if (Util_ParseC_MatchKeyword(&thread, "baseframe"))
+ {
+ NUint32 jointnum;
+ ExpectKeyword("{", "after 'baseframe'");
+ modelanim->basevalues = Mem_Alloc(r->memzone, modelanim->numtransforms * 6 * sizeof(*modelanim->basevalues));
+ modelanim->values = Mem_Alloc(r->memzone, modelanim->numframes * modelanim->numvaluesperframe * sizeof(*modelanim->values));
+ for (jointnum = 0; !Util_ParseC_MatchKeyword(&thread, "}");jointnum++)
+ {
+ // ( 0.000000 0.000000 0.000000 ) ( -0.707107 0.000000 -0.000000 )
+ ExpectKeyword("(", "before first joint data list");
+ LoadValue(modelanim->basevalues[jointnum*6+0], "(joint 0)");
+ LoadValue(modelanim->basevalues[jointnum*6+1], "(joint 1)");
+ LoadValue(modelanim->basevalues[jointnum*6+2], "(joint 2)");
+ ExpectKeyword(")", "after first joint data list");
+ ExpectKeyword("(", "before second joint data list");
+ LoadValue(modelanim->basevalues[jointnum*6+3], "(joint 3)");
+ LoadValue(modelanim->basevalues[jointnum*6+4], "(joint 4)");
+ LoadValue(modelanim->basevalues[jointnum*6+5], "(joint 5)");
+ ExpectKeyword(")", "after second joint data list");
+ }
+ if (jointnum != modelanim->numtransforms)
+ {
+ Console_Printf("ModelAnim_Load: final jointnum (%i) != numJoints (%i)\n", jointnum, modelanim->numtransforms);
+ Abort();
+ }
+ }
+ //frame 0 {
+ else if (Util_ParseC_MatchKeyword(&thread, "frame"))
+ {
+ NUint32 framenum;
+ NUint32 valuenum;
+ float *values;
+ LoadInt(framenum, "number of frames");
+ if (framenum < 0 || framenum >= modelanim->numframes)
+ {
+ Console_Printf("ModelAnim_Load: frame number %i < 0 || frame number %i >= numFrames (%i)\n", framenum, framenum, modelanim->numframes);
+ Abort();
+ }
+ ExpectKeyword("{", "after 'frame'");
+ values = modelanim->values + framenum * modelanim->numvaluesperframe;
+ for (valuenum = 0; !Util_ParseC_MatchKeyword(&thread, "}");valuenum++)
+ {
+ if (valuenum >= modelanim->numvaluesperframe)
+ {
+ Console_Printf("ModelAnim_Load: too many components in frame %i\n", framenum);
+ Abort();
+ }
+ LoadValue(values[valuenum], "component value");
+ }
+ if (valuenum != modelanim->numvaluesperframe)
+ {
+ Console_Printf("ModelAnim_Load: final component (%i) != numAnimatedComponents (%i)\n", valuenum, modelanim->numvaluesperframe);
+ Abort();
+ }
+ }
+ }
+ Util_ParseC_CleanUpThread(&thread);
+ Mem_Free(&filedata);
+ // if there was a load error, don't point to the Model so nothing will try
+ // to use the incomplete data
+ if (!error)
+ r->data = modelanim;
+#undef Abort
+#undef LoadInt
+#undef LoadValue
+#undef LoadString
+#undef ExpectKeyword
+}
+
+void ModelAnim_Unload(ResourceEntry *r)
+{
+ // freeing of the memzone will get rid of the modelanim
+}
+
+NUint32 ModelAnim_GetNumTransforms(NUint32 resourceindex)
+{
+ ModelAnim *modelanim;
+ modelanim = Resource_GetData(resourceindex);
+ if (!modelanim)
+ return 0; // no modelanim
+ return modelanim->numtransforms;
+}
+
+NUint32 ModelAnim_GetNumFrames(NUint32 resourceindex)
+{
+ ModelAnim *modelanim;
+ modelanim = Resource_GetData(resourceindex);
+ if (!modelanim)
+ return 0; // no modelanim
+ return modelanim->numframes;
+}
+
+double ModelAnim_GetFrameRate(NUint32 resourceindex)
+{
+ ModelAnim *modelanim;
+ modelanim = Resource_GetData(resourceindex);
+ if (!modelanim)
+ return 0; // no modelanim
+ return modelanim->framerate;
+}
+
+void ModelAnim_BlendPoses(NUint32 modelanimresource, NUint32 modelresource, NUint32 frame1, NUint32 frame2, float framelerp, matrix4x4_t *transforms, Nbool clearfirst)
+{
+ NUint32 transformnum;
+ float iframelerp = 1 - framelerp;
+ const float *v1, *v2, *b;
+ Model *model;
+ ModelAnim *modelanim;
+ ModelAnim_TransformInfo *info;
+ modelanim = Resource_GetData(modelanimresource);
+ if (!modelanim)
+ return; // no modelanim
+ model = Resource_GetData(modelresource);
+ if (!model)
+ return; // no model
+ if (model->numtransforms != modelanim->numtransforms)
+ return; // error
+ v1 = modelanim->values + frame1 * modelanim->numvaluesperframe;
+ v2 = modelanim->values + frame2 * modelanim->numvaluesperframe;
+ b = modelanim->basevalues;
+ for (transformnum = 0, info = modelanim->transforminfo;transformnum < modelanim->numtransforms;transformnum++, info++, b += 6)
+ {
+ NUint32 component;
+ NUint32 valueflags = info->valueflags;
+ const float *f1 = v1 + info->firstvalue;
+ const float *f2 = v2 + info->firstvalue;
+ float pose[6];
+ matrix4x4_t posematrix, relativematrix;
+ for (component = 0;component < 6;component++)
+ {
+ if (valueflags & (1<<component))
+ pose[component] = *f1++ * iframelerp + *f2++ * framelerp;
+ else
+ pose[component] = b[component];
+ }
+ Matrix4x4_CreateFromDoom3Joint(&posematrix, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5]);
+ Matrix4x4_Concat(&relativematrix, &posematrix, &model->baseinversetransforms[transformnum]);
+ }
+}
Added: trunk/modelanim.h
===================================================================
--- trunk/modelanim.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/modelanim.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -0,0 +1,35 @@
+
+typedef struct ModelAnim_TransformInfo
+{
+ char *name;
+ NUint32 parentindex;
+ NUint32 valueflags;
+ NUint32 firstvalue;
+ NUint32 numvalues;
+}
+ModelAnim_TransformInfo;
+
+typedef struct ModelAnim
+{
+ // md5anim files store a baseline (default values) of the entire joint set,
+ // and then flags for which values are animated, since most of the joint
+ // set is unchanging in most animations
+ // each joint is 6 values (3 location, 3 quaternion)
+ // the quaternions are stored as canonical unit vectors in which w is
+ // assumed to be negative (it is easy to regenerate any one component of a
+ // unit vector if you know its sign)
+ NUint32 numtransforms;
+ NUint32 numvaluesperframe;
+ NUint32 numframes;
+ float framerate;
+ ModelAnim_TransformInfo *transforminfo; // [numtransforms]
+ float *values; // [numframes*numvaluesperframe]
+ float *basevalues; // [numtransforms*6]
+}
+ModelAnim;
+
+void ModelAnim_Load(ResourceEntry *r);
+void ModelAnim_Unload(ResourceEntry *r);
+
+NUint32 ModelAnim_GetNumTransforms(NUint32 resourceindex);
+void ModelAnim_GetTransforms(NUint32 resourceindex, NUint32 frame1, NUint32 frame2, float framelerp, matrix4x4_t *transforms);
Modified: trunk/resource.c
===================================================================
--- trunk/resource.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/resource.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -2,6 +2,7 @@
#include "ncommon.h"
#include "material.h"
#include "model.h"
+#include "modelanim.h"
#include "sound.h"
#include "texture.h"
#include "video.h"
@@ -182,6 +183,9 @@
case RESOURCETYPE_MODEL:
Model_Load(r);
break;
+ case RESOURCETYPE_MODELANIM:
+ ModelAnim_Load(r);
+ break;
case RESOURCETYPE_SOUND:
Sound_Load(r);
break;
@@ -221,6 +225,9 @@
case RESOURCETYPE_MODEL:
Model_Unload(r);
break;
+ case RESOURCETYPE_MODELANIM:
+ ModelAnim_Unload(r);
+ break;
case RESOURCETYPE_SOUND:
Sound_Unload(r);
break;
Modified: trunk/resource.h
===================================================================
--- trunk/resource.h 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/resource.h 2006-03-27 09:16:27 UTC (rev 685)
@@ -28,6 +28,7 @@
{
RESOURCETYPE_INVALID = 0,
RESOURCETYPE_MODEL,
+ RESOURCETYPE_MODELANIM,
RESOURCETYPE_SOUND,
RESOURCETYPE_MATERIAL,
RESOURCETYPE_TEXTURE,
Modified: trunk/system.c
===================================================================
--- trunk/system.c 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/system.c 2006-03-27 09:16:27 UTC (rev 685)
@@ -30,6 +30,20 @@
R_Quit();
if (openglmode)
{
+ // hack to work around SDL not resetting the SDL_GL_SetAttribute stuff
+ // until we open a non-GL window
+ if (Video.running)
+ {
+ if (Video.openglmode)
+ DynGL_CloseLibrary();
+ SDL_WM_SetCaption ("DarkWar", "DarkWar");
+ Video_Surface = SDL_SetVideoMode(width, height, bpp, SDL_HWSURFACE | (fullscreen ? SDL_FULLSCREEN : 0));
+ if (!Video_Surface)
+ {
+ Console_Printf("Could not open video: %s.\n", SDL_GetError());
+ return false;
+ }
+ }
if (!DynGL_LoadLibrary(NULL))
{
char *error = SDL_GetError();
@@ -71,7 +85,8 @@
Video.fullscreen = fullscreen;
Video.openglmode = openglmode;
Video.framecount = 0;
- DynGL_GetFunctions(NULL);
+ if (openglmode)
+ DynGL_GetFunctions(NULL);
R_Init();
Input.hasfocus = true; //this ought to be true just after initialization (SDL doesn't seem to tell us either way).
Modified: trunk/todo
===================================================================
--- trunk/todo 2006-03-27 09:14:49 UTC (rev 684)
+++ trunk/todo 2006-03-27 09:16:27 UTC (rev 685)
@@ -15,3 +15,4 @@
d bug darkwar console: cursoring left on the commandline and editing the text discards the rest of the line
d change darkwar drawview: redesign G_DrawView to cull surfaces of entities
d change darkwar util: util_maketerrain should emit only one md5mesh file with all the surfaces in it
+0 bug darkwar networking: attached entities should add dependencies to their owner so that if the owner update is lost and no more recent update of the child exists it forces an update of the child so that the child can attach properly
\ No newline at end of file
More information about the neither-commits
mailing list