gentity_t *CreateMissile( vector3 *org, vector3 *dir, float vel, int life, gentity_t *owner, qboolean altFire ) { gentity_t *missile = G_Spawn(); missile->nextthink = level.time + life; missile->think = G_FreeEntity; missile->s.eType = ET_MISSILE; missile->r.svFlags = SVF_USE_CURRENT_ORIGIN; missile->parent = owner; missile->r.ownerNum = owner->s.number; if ( altFire ) { missile->s.eFlags |= EF_ALT_FIRING; } missile->s.pos.trType = TR_LINEAR; missile->s.pos.trTime = level.time;// - MISSILE_PRESTEP_TIME; // NOTENOTE This is a Quake 3 addition over JK2 missile->target_ent = NULL; VectorSnap( org ); VectorCopy( org, &missile->s.pos.trBase ); VectorScale( dir, vel, &missile->s.pos.trDelta ); VectorCopy( org, &missile->r.currentOrigin ); VectorSnap( &missile->s.pos.trDelta ); //Raz: Save the velocity for portals reorienting projectiles { byteAlias_t ba; ba.f = vel; missile->genericValue1 = ba.i; } missile->genericValue2 = life; return missile; }
//QtZ: From Jedi Academy gentity_t *CreateMissile( vector3 *org, vector3 *dir, float vel, int life, gentity_t *owner) { gentity_t *missile = G_Spawn(); missile->nextthink = level.time + life; missile->think = G_FreeEntity; missile->s.eType = ET_MISSILE; missile->r.svFlags = SVF_USE_CURRENT_ORIGIN; missile->parent = owner; missile->r.ownerNum = owner->s.number; missile->s.pos.trType = TR_LINEAR; missile->s.pos.trTime = level.time;// - MISSILE_PRESTEP_TIME; // NOTENOTE This is a Quake 3 addition over JK2 missile->target_ent = NULL; VectorSnap( org ); VectorCopy( org, &missile->s.pos.trBase ); VectorScale( dir, vel, &missile->s.pos.trDelta ); VectorCopy( org, &missile->r.currentOrigin ); VectorSnap( &missile->s.pos.trDelta ); //Raz: Added missile->knockbackMulti = 1.0f; missile->knockbackMultiSelf = 1.0f; return missile; }
gentity_t *fire_grapple( gentity_t *self, vector3 *start, vector3 *dir ) { gentity_t *hook; VectorNormalize( dir ); hook = CreateMissile( start, dir, japp_hookSpeed.value, 10000, self, qfalse );//G_Spawn(); hook->classname = "hook"; hook->nextthink = level.time + 10000; hook->think = Weapon_HookFree; hook->s.eType = ET_MISSILE; hook->r.svFlags = SVF_USE_CURRENT_ORIGIN; hook->s.weapon = WP_STUN_BATON;//WP_BRYAR_PISTOL hook->r.ownerNum = self->s.number; hook->methodOfDeath = MOD_STUN_BATON; hook->clipmask = 267009/*MASK_SHOT*/; //From JA+ hook->parent = self; hook->target_ent = NULL; hook->s.pos.trType = TR_LINEAR; hook->s.pos.trTime = level.time - japp_hookSpeed.integer; hook->s.otherEntityNum = self->s.number; // Used to match beam in client if ( self->client->pers.adminData.isGhost ) { hook->r.svFlags |= SVF_SINGLECLIENT; hook->r.singleClient = self->s.number; } VectorCopy( start, &hook->s.pos.trBase ); VectorScale( dir, 800, &hook->s.pos.trDelta ); VectorSnap( &hook->s.pos.trDelta ); // Save net bandwidth VectorCopy( start, &hook->r.currentOrigin ); return hook; }
// Explode a missile without an impact void G_ExplodeMissile( gentity_t *ent ) { vector3 dir; vector3 origin; BG_EvaluateTrajectory( &ent->s.pos, level.time, &origin ); VectorSnap( &origin ); G_SetOrigin( ent, &origin ); // we don't have a valid direction, so just point straight up dir.x = dir.y = 0; dir.z = 1; ent->s.eType = ET_GENERAL; G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( &dir ) ); ent->freeAfterEvent = qtrue; ent->takedamage = qfalse; // splash damage if ( ent->splashDamage ) { if ( G_RadiusDamage( &ent->r.currentOrigin, ent->parent, ent->splashDamage, ent->splashRadius, ent, ent, ent->splashMethodOfDeath ) ) { if ( ent->parent ) { g_entities[ent->parent->s.number].client->accuracy_hits++; } else if ( ent->activator ) { g_entities[ent->activator->s.number].client->accuracy_hits++; } } } trap->LinkEntity( (sharedEntity_t *)ent ); }
// Explode a missile without an impact void G_ExplodeMissile( gentity_t *ent ) { vector3 dir = { 0.0f, 0.0f, 1.0f }, origin = { 0.0f }; BG_EvaluateTrajectory( &ent->s.pos, level.time, &origin ); VectorSnap( &origin ); G_SetOrigin( ent, &origin ); ent->s.eType = ET_GENERAL; G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( &dir ) ); ent->freeAfterEvent = qtrue; ent->takedamage = qfalse; if ( ent->splashDamage || ent->splashRadius ) { if ( G_RadiusDamage( &ent->r.currentOrigin, ent->parent, (float)ent->splashDamage, (float)ent->splashRadius, ent, ent, ent->splashMethodOfDeath ) ) { if ( ent->parent ) g_entities[ent->parent->s.number].client->accuracy_hits++; else if ( ent->activator ) g_entities[ent->activator->s.number].client->accuracy_hits++; } } trap->SV_LinkEntity( (sharedEntity_t *)ent ); }
void G_BounceItem( gentity_t *ent, trace_t *trace ) { vector3 velocity; float dot; int hitTime; // reflect the velocity on the trace plane hitTime = level.previousTime + (int)((level.time - level.previousTime) * trace->fraction); BG_EvaluateTrajectoryDelta( &ent->s.pos, hitTime, &velocity ); dot = DotProduct( &velocity, &trace->plane.normal ); VectorMA( &velocity, -2*dot, &trace->plane.normal, &ent->s.pos.trDelta ); // cut the velocity to keep from bouncing forever VectorScale( &ent->s.pos.trDelta, ent->physicsBounce, &ent->s.pos.trDelta ); // check for stop if ( trace->plane.normal.z > 0 && ent->s.pos.trDelta.z < 40 ) { trace->endpos.z += 1.0f; // make sure it is off ground VectorSnap( &trace->endpos ); G_SetOrigin( ent, &trace->endpos ); ent->s.groundEntityNum = trace->entityNum; return; } VectorAdd( &ent->r.currentOrigin, &trace->plane.normal, &ent->r.currentOrigin); VectorCopy( &ent->r.currentOrigin, &ent->s.pos.trBase ); ent->s.pos.trTime = level.time; }
// Spawns an event entity that will be auto-removed // The origin will be snapped to save net bandwidth, so care must be taken if the // origin is right on a surface (snap towards start vector first) gentity_t *G_TempEntity( vector3 *origin, int event ) { gentity_t *e; vector3 snapped; e = G_Spawn(); e->s.eType = ET_EVENTS + event; e->classname = "tempEntity"; e->eventTime = level.time; e->freeAfterEvent = qtrue; VectorCopy( origin, &snapped ); VectorSnap( &snapped ); // save network bandwidth G_SetOrigin( e, &snapped ); // find cluster for PVS trap->SV_LinkEntity( (sharedEntity_t *)e ); return e; }
qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax) { if (e->modelpath != NULL) { if (e->model == NULL) { e->model = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t))); } char *pModelBuff = strdup(e->modelpath); char *pSkinBuff = NULL; if (e->skinpath) { pSkinBuff = strdup(e->skinpath); } CStringList Models; CStringList Skins; char* pToken = strtok(pModelBuff, ";\0"); while (pToken != NULL) { Models.AddTail(pToken); pToken = strtok(NULL, ";\0"); } if (pSkinBuff != NULL) { pToken = strtok(pSkinBuff, ";\0"); while (pToken != NULL) { Skins.AddTail(pToken); pToken = strtok(NULL, ";\0"); } } entitymodel *model = e->model; int i = 0; for (; i < Models.GetCount(); i++) { char *pSkin = NULL; if (i < Skins.GetCount()) { pSkin = Skins.GetAt(Skins.FindIndex(i)).GetBuffer(0); } LoadModel(Models.GetAt(Models.FindIndex(i)), e, vMin, vMax, model, pSkin); model->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t))); model = model->pNext; } // at this poitn vMin and vMax contain the min max of the model // which needs to be centered at origin 0, 0, 0 VectorSnap(vMin); VectorSnap(vMax); if (vMax[0] - vMin[0] < 2) { vMin[0] -= 1; vMax[0] += 1; } if (vMin[1] - vMax[1] < 2) { vMin[1] -= 1; vMax[1] += 1; } if (vMax[2] - vMin[2] < 2) { vMax[2] -= 1; vMax[2] += 1; } vec3_t vTemp; VectorAdd(vMin, vMax, vTemp); VectorScale(vTemp, 0.5, vTemp); model = e->model; while (model != NULL) { for (i = 0; i < model->nTriCount; i++) { for (int j = 0; j < 3; j++) { ;//VectorSubtract(model->pTriList[i].v[j], vTemp, model->pTriList[i].v[j]); } } model = model->pNext; } free(pModelBuff); free(e->modelpath); e->modelpath = NULL; if(e->skinpath) { free(e->skinpath); e->skinpath = NULL; free(pSkinBuff); } } return (e->model != NULL && e->model->nTriCount > 0); }
static void turretG2_fire( gentity_t *ent, vector3 *start, vector3 *dir ) { vector3 org, ang; gentity_t *bolt; if ( (trap->PointContents( start, ent->s.number )&MASK_SHOT) ) { return; } VectorMA( start, -START_DIS, dir, &org ); // dumb.... if ( ent->random ) { vectoangles( dir, &ang ); ang.pitch += flrand( -ent->random, ent->random ); ang.yaw += flrand( -ent->random, ent->random ); AngleVectors( &ang, dir, NULL, NULL ); } vectoangles( dir, &ang ); if ( (ent->spawnflags&SPF_TURRETG2_TURBO) ) { //muzzle flash G_PlayEffectID( ent->genericValue13, &org, &ang ); WP_FireTurboLaserMissile( ent, start, dir ); if ( ent->alt_fire ) { TurboLaser_SetBoneAnim( ent, 2, 3 ); } else { TurboLaser_SetBoneAnim( ent, 0, 1 ); } } else { G_PlayEffectID( G_EffectIndex( "blaster/muzzle_flash" ), &org, &ang ); bolt = G_Spawn(); bolt->classname = "turret_proj"; bolt->nextthink = level.time + 10000; bolt->think = G_FreeEntity; bolt->s.eType = ET_MISSILE; bolt->s.weapon = WP_BLASTER; bolt->r.ownerNum = ent->s.number; bolt->damage = ent->damage; bolt->alliedTeam = ent->alliedTeam; bolt->teamnodmg = ent->teamnodmg; bolt->dflags = (DAMAGE_NO_KNOCKBACK | DAMAGE_HEAVY_WEAP_CLASS); // Don't push them around, or else we are constantly re-aiming bolt->splashDamage = ent->splashDamage; bolt->splashRadius = ent->splashDamage; bolt->methodOfDeath = MOD_TARGET_LASER;//MOD_ENERGY; bolt->splashMethodOfDeath = MOD_TARGET_LASER;//MOD_ENERGY; bolt->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; //bolt->trigger_formation = qfalse; // don't draw tail on first frame VectorSet( &bolt->r.maxs, 1.5f, 1.5f, 1.5f ); VectorScale( &bolt->r.maxs, -1, &bolt->r.mins ); bolt->s.pos.trType = TR_LINEAR; bolt->s.pos.trTime = level.time; VectorCopy( start, &bolt->s.pos.trBase ); VectorScale( dir, ent->mass, &bolt->s.pos.trDelta ); VectorSnap( &bolt->s.pos.trDelta ); // save net bandwidth VectorCopy( start, &bolt->r.currentOrigin ); } }