===============================================================================
*/
+void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
+{
+ prvm_eval_t *val;
+ prog->globals.server->self = PRVM_EDICT_TO_PROG(touch);
+ prog->globals.server->other = PRVM_EDICT_TO_PROG(ent);
+ prog->globals.server->time = sv.time;
+ prog->globals.server->trace_allsolid = false;
+ prog->globals.server->trace_startsolid = false;
+ prog->globals.server->trace_fraction = 1;
+ prog->globals.server->trace_inwater = false;
+ prog->globals.server->trace_inopen = true;
+ VectorCopy (touch->fields.server->origin, prog->globals.server->trace_endpos);
+ VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1);
+ prog->globals.server->trace_plane_dist = 0;
+ prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(ent);
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
+ val->_float = 0;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
+ val->_float = 0;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
+ val->_float = 0;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
+ val->string = 0;
+ PRVM_ExecuteProgram (touch->fields.server->touch, "QC function self.touch is missing");
+}
+
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
{
int i, numtouchedicts, old_self, old_other;
touch = touchedicts[i];
if (touch != ent && (int)touch->fields.server->solid == SOLID_TRIGGER && touch->fields.server->touch)
{
- prvm_eval_t *val;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(touch);
- prog->globals.server->other = PRVM_EDICT_TO_PROG(ent);
- prog->globals.server->time = sv.time;
- prog->globals.server->trace_allsolid = false;
- prog->globals.server->trace_startsolid = false;
- prog->globals.server->trace_fraction = 1;
- prog->globals.server->trace_inwater = false;
- prog->globals.server->trace_inopen = true;
- VectorCopy (touch->fields.server->origin, prog->globals.server->trace_endpos);
- VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1);
- prog->globals.server->trace_plane_dist = 0;
- prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(ent);
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
- val->_float = 0;
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
- val->_float = 0;
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
- val->_float = 0;
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
- val->string = 0;
- PRVM_ExecuteProgram (touch->fields.server->touch, "QC function self.touch is missing");
+ SV_LinkEdict_TouchAreaGrid_Call(touch, ent);
}
}
prog->globals.server->self = old_self;
prog->globals.server->other = old_other;
}
+static void RotateBBox(const vec3_t mins, const vec3_t maxs, const vec3_t angles, vec3_t rotatedmins, vec3_t rotatedmaxs)
+{
+ vec3_t v, u;
+ matrix4x4_t m;
+ Matrix4x4_CreateFromQuakeEntity(&m, 0, 0, 0, angles[PITCH], angles[YAW], angles[ROLL], 1.0);
+
+ v[0] = mins[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ VectorCopy(u, rotatedmins); VectorCopy(u, rotatedmaxs);
+ v[0] = maxs[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = mins[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = maxs[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = mins[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = maxs[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = mins[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = maxs[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+}
+
/*
===============
SV_LinkEdict
// set the abs box
- if (ent->fields.server->solid == SOLID_BSP)
+ if (ent->fields.server->movetype == MOVETYPE_PHYSICS)
+ {
+ // TODO maybe should do this for rotating SOLID_BSP too? Would behave better with rotating doors
+ // TODO special handling for spheres?
+ RotateBBox(ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->angles, mins, maxs);
+ VectorAdd(ent->fields.server->origin, mins, mins);
+ VectorAdd(ent->fields.server->origin, maxs, maxs);
+ }
+ else if (ent->fields.server->solid == SOLID_BSP)
{
int modelindex = (int)ent->fields.server->modelindex;
if (modelindex < 0 || modelindex >= MAX_MODELS)
//int (ODE_API *dSpaceGetClass)(dSpaceID space);
//
void (ODE_API *dGeomDestroy)(dGeomID geom);
-//void (ODE_API *dGeomSetData)(dGeomID geom, void* data);
-//void * (ODE_API *dGeomGetData)(dGeomID geom);
+void (ODE_API *dGeomSetData)(dGeomID geom, void* data);
+void * (ODE_API *dGeomGetData)(dGeomID geom);
void (ODE_API *dGeomSetBody)(dGeomID geom, dBodyID body);
dBodyID (ODE_API *dGeomGetBody)(dGeomID geom);
void (ODE_API *dGeomSetPosition)(dGeomID geom, dReal x, dReal y, dReal z);
VectorCopy(angles, ed->priv.server->ode_angles);
VectorCopy(avelocity, ed->priv.server->ode_avelocity);
ed->priv.server->ode_gravity = dBodyGetGravityMode(body);
+
+ if(!strcmp(prog->name, "server")) // FIXME some better way?
+ {
+ SV_LinkEdict(ed);
+ SV_LinkEdict_TouchAreaGrid(ed);
+ }
}
static void World_Physics_Frame_JointFromEntity(world_t *world, prvm_edict_t *ed)
Matrix4x4_Invert_Simple(&ed->priv.server->ode_offsetimatrix, &ed->priv.server->ode_offsetmatrix);
}
+ if(ed->priv.server->ode_geom)
+ dGeomSetData(ed->priv.server->ode_geom, (void*)ed);
if (movetype == MOVETYPE_PHYSICS && ed->priv.server->ode_geom)
{
if (ed->priv.server->ode_body == NULL)
matrix4x4_t entitymatrix;
matrix4x4_t bodymatrix;
+#if 0
Con_Printf("entity %i got changed by QC\n", (int) (ed - prog->edicts));
if(!VectorCompare(origin, ed->priv.server->ode_origin))
Con_Printf(" origin: %f %f %f -> %f %f %f\n", ed->priv.server->ode_origin[0], ed->priv.server->ode_origin[1], ed->priv.server->ode_origin[2], origin[0], origin[1], origin[2]);
Con_Printf(" avelocity: %f %f %f -> %f %f %f\n", ed->priv.server->ode_avelocity[0], ed->priv.server->ode_avelocity[1], ed->priv.server->ode_avelocity[2], avelocity[0], avelocity[1], avelocity[2]);
if(gravity != ed->priv.server->ode_gravity)
Con_Printf(" gravity: %i -> %i\n", ed->priv.server->ode_gravity, gravity);
+#endif
// values for BodyFromEntity to check if the qc modified anything later
VectorCopy(origin, ed->priv.server->ode_origin);
float bouncefactor2 = 0.0f;
float bouncestop2 = 60.0f / 800.0f;
dVector3 grav;
- prvm_edict_t *ed;
+ prvm_edict_t *ed1, *ed2;
if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
{
if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact))
return;
- if(b1)
+ ed1 = (prvm_edict_t *) dGeomGetData(o1);
+ if(ed1 && ed1->priv.server->free)
+ ed1 = NULL;
+ if(ed1)
{
- ed = (prvm_edict_t *) dBodyGetData(b1);
- if(ed)
- {
- val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncefactor);
- if (val!=0 && val->_float)
- bouncefactor1 = val->_float;
+ val = PRVM_EDICTFIELDVALUE(ed1, prog->fieldoffsets.bouncefactor);
+ if (val!=0 && val->_float)
+ bouncefactor1 = val->_float;
- val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncestop);
- if (val!=0 && val->_float)
- bouncestop1 = val->_float;
- }
+ val = PRVM_EDICTFIELDVALUE(ed1, prog->fieldoffsets.bouncestop);
+ if (val!=0 && val->_float)
+ bouncestop1 = val->_float;
}
- if(b2)
+ ed2 = (prvm_edict_t *) dGeomGetData(o2);
+ if(ed2 && ed2->priv.server->free)
+ ed2 = NULL;
+ if(ed2)
{
- ed = (prvm_edict_t *) dBodyGetData(b2);
- if(ed)
- {
- val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncefactor);
- if (val!=0 && val->_float)
- bouncefactor2 = val->_float;
+ val = PRVM_EDICTFIELDVALUE(ed2, prog->fieldoffsets.bouncefactor);
+ if (val!=0 && val->_float)
+ bouncefactor2 = val->_float;
- val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncestop);
- if (val!=0 && val->_float)
- bouncestop2 = val->_float;
+ val = PRVM_EDICTFIELDVALUE(ed2, prog->fieldoffsets.bouncestop);
+ if (val!=0 && val->_float)
+ bouncestop2 = val->_float;
+ }
+
+ if(!strcmp(prog->name, "server"))
+ {
+ if(ed1 && ed1->fields.server->touch)
+ {
+ SV_LinkEdict_TouchAreaGrid_Call(ed1, ed2 ? ed2 : prog->edicts);
+ }
+ if(ed2 && ed2->fields.server->touch)
+ {
+ SV_LinkEdict_TouchAreaGrid_Call(ed2, ed1 ? ed1 : prog->edicts);
}
}