/** * @brief Make the actor use (as in open/close) a door edict * @note Will also check whether the door is still reachable (this might have * changed due to the rotation) after the usage * @param actor The actor that is using the door * @param door The door that should be opened/closed */ void G_ActorUseDoor (Edict* actor, Edict* door) { /* check whether it's part of an edict group but not the master */ if (door->flags & FL_GROUPSLAVE) door = door->groupMaster; if (!G_ClientUseEdict(actor->getPlayer(), actor, door)) return; /* end this loop here, for the AI this is a) not interesting, * and b) could result in endless loops */ if (G_IsAI(actor)) return; Edict* closeActor = nullptr; while ((closeActor = G_FindRadius(closeActor, door->origin, UNIT_SIZE * 3))) { /* check whether the door is still reachable (this might have * changed due to the rotation) or whether an actor can reach it now */ G_TouchTriggers(closeActor); } }
/** * @brief Actually does the magic */ static void G_weapon_chaingun_Think(g_entity_t *ent) { g_entity_t *cg = NULL; while ((cg = G_Find(cg, EOFS(class_name), "weapon_chaingun"))) { // spawn a lightning gun where we are g_entity_t *lg = G_AllocEntity_(g_media.items.weapons[WEAPON_LIGHTNING]->class_name); VectorCopy(cg->s.origin, lg->s.origin); VectorCopy(cg->s.angles, lg->s.angles); lg->locals.spawn_flags = cg->locals.spawn_flags; G_SpawnItem(lg, g_media.items.weapons[WEAPON_LIGHTNING]); // replace nearby bullets with bolts g_entity_t *ammo = NULL; while ((ammo = G_FindRadius(ammo, lg->s.origin, 128.0))) { if (ammo->locals.item && ammo->locals.item == g_media.items.ammo[AMMO_BULLETS]) { // hello bolts g_entity_t *bolts = G_AllocEntity_(g_media.items.ammo[AMMO_BOLTS]->class_name); VectorCopy(ammo->s.origin, bolts->s.origin); VectorCopy(ammo->s.angles, bolts->s.angles); bolts->locals.spawn_flags = ammo->locals.spawn_flags; G_SpawnItem(bolts, g_media.items.ammo[AMMO_BOLTS]); // byebye bullets G_FreeEntity(ammo); } } // byebye chaingun G_FreeEntity(cg); } }
void G_HomingMissile(gentity_t * ent) { gentity_t *target = NULL; gentity_t *blip = NULL; vec3_t dir, blipdir; vec_t angle; qboolean chaff; //qboolean ignorechaff = qfalse; const int HOMING_THINK_TIME = 60; // explode after 15 seconds without a hit if(ent->spawnTime + 15000 <= level.time) { G_ExplodeMissile(ent); return; } /* if(ent->parent->health <= 0) { ent->nextthink = level.time + 15000; ent->think = G_ExplodeMissile; return; } */ /* if(ent->parent && ent->parent->client) { ignorechaff = (ent->parent->client->ps.powerups[PW_ACCURACY] > 0); } */ while((blip = G_FindRadius(blip, ent->r.currentOrigin, 2000)) != NULL) { #if 0 if(blip->s.weapon == WP_CHAFF) { if(ignorechaff) { continue; } chaff = qtrue; } else #endif { chaff = qfalse; if(blip->client == NULL) continue; if(blip == ent->parent) continue; if(blip->health <= 0) continue; if(blip->client->sess.sessionTeam >= TEAM_SPECTATOR) continue; if((g_gametype.integer == GT_TEAM || g_gametype.integer == GT_CTF) && OnSameTeam(blip, ent->parent)) continue; } if(!G_IsVisible(ent, blip->r.currentOrigin)) continue; VectorSubtract(blip->r.currentOrigin, ent->r.currentOrigin, blipdir); if(chaff) { VectorScale(blipdir, 0.5, blipdir); } if((target == NULL) || (VectorLength(blipdir) < VectorLength(dir))) { if(chaff) { VectorScale(blipdir, 2, blipdir); } angle = AngleBetweenVectors(ent->r.currentAngles, blipdir); if(angle < 120.0f) { // We add it as our target target = blip; VectorCopy(blipdir, dir); } } } if(target == NULL) { ent->nextthink = level.time + HOMING_THINK_TIME; // + 10000; ent->think = G_HomingMissile; } else { // for exact trajectory calculation, set current point to base. VectorCopy(ent->r.currentOrigin, ent->s.pos.trBase); VectorNormalize(dir); // 0.5 is swing rate. VectorScale(dir, 0.5, dir); VectorAdd(dir, ent->r.currentAngles, dir); // turn nozzle to target angle VectorNormalize(dir); VectorCopy(dir, ent->r.currentAngles); // scale direction, put into trDelta if(g_rocketAcceleration.integer) { // use acceleration instead of linear velocity ent->s.pos.trType = TR_ACCELERATION; ent->s.pos.trAcceleration = g_rocketAcceleration.value; VectorScale(dir, g_rocketVelocity.value, ent->s.pos.trDelta); } else { ent->s.pos.trType = TR_LINEAR; VectorScale(dir, g_rocketVelocity.value * 0.25, ent->s.pos.trDelta); } ent->s.pos.trTime = level.time; SnapVector(ent->s.pos.trDelta); // save net bandwidth ent->nextthink = level.time + HOMING_THINK_TIME; // decrease this value also makes fast swing ent->think = G_HomingMissile; //G_Printf("targeting %s\n", target->classname); } }
/* ================ G_HomingMissile From XREAL r3036 ================ */ void G_HomingMissile(gentity_t * ent) { gentity_t *target = NULL; gentity_t *blip = NULL; vec3_t dir, blipdir; vec_t angle; const int HOMING_THINK_TIME = 60; #ifdef TA_WEAPSYS // XREAL: spawnTime // explode after 15 seconds without a hit if (bg_projectileinfo[ent->s.weapon].timetolive != -1 && ent->spawnTime + bg_projectileinfo[ent->s.weapon].timetolive <= level.time) { G_ExplodeMissile(ent); return; } #endif /* if(ent->parent->health <= 0) { ent->nextthink = level.time + 15000; ent->think = G_ExplodeMissile; return; } */ while((blip = G_FindRadius(blip, ent->r.currentOrigin, 2000)) != NULL) { if(blip->player == NULL) continue; if(blip == ent->parent) continue; if(blip->health <= 0) continue; if(blip->flags & FL_NOTARGET) continue; if(blip->player->sess.sessionTeam >= TEAM_SPECTATOR) continue; if(OnSameTeam(blip, ent->parent)) continue; if(!G_IsVisible(ent->s.number, ent->r.currentOrigin, blip->r.currentOrigin)) continue; VectorSubtract(blip->r.currentOrigin, ent->r.currentOrigin, blipdir); if((target == NULL) || (VectorLength(blipdir) < VectorLength(dir))) { angle = AngleBetweenVectors(ent->r.currentAngles, blipdir); if(angle < 120.0f) { // We add it as our target target = blip; VectorCopy(blipdir, dir); } } } if (target == NULL) { ent->nextthink = level.time + HOMING_THINK_TIME; // + 10000; ent->think = G_HomingMissile; } else { // for exact trajectory calculation, set current point to base. VectorCopy(ent->r.currentOrigin, ent->s.pos.trBase); VectorNormalize(dir); // 0.5 is swing rate. VectorScale(dir, 0.5, dir); VectorAdd(dir, ent->r.currentAngles, dir); // turn nozzle to target angle VectorNormalize(dir); VectorCopy(dir, ent->r.currentAngles); ent->s.pos.trTime = level.time; G_SetMissileVelocity(ent, dir, ent->s.weapon); ent->nextthink = level.time + HOMING_THINK_TIME; // decrease this value also makes fast swing ent->think = G_HomingMissile; //G_Printf("targeting %s\n", target->classname); } }