|
TUTORIAL 11 - Vortex Grenades
von AssKicka
Dieses mal werden wir die normalen grenades in vortex grenades verwandeln.
Hä, wie was vortex ? Die grenade wird den Spieler quasi einsaugen, oder
zumindest eine Anziehungskraft auf ihn auswirken. Wenn der Spieler sie
dann berührt, explodiert sie.
1. Der Spion
Zuerst benötigen wir eine Hilfsfunktion, um den Umkreis der grenade
nach potentiellen Opfern abzusuchen. Füge folgende Funktion ans
Ende der Datei g_utils.c:
/*
================
findradius
================
*/
gentity_t *findradius (gentity_t *ent, vec3_t org, float rad) {
vec3_t eorg;
int j;
if (!ent)
ent = g_entities;
else
ent++;
for (; ent < &g_entities[level.num_entities]; ent++)
{
if (!ent->inuse)
continue;
for (j=0; j<3; j++)
eorg[j] = org[j] - (ent->r.currentOrigin[j] +
(ent->r.mins[j] + ent->r.maxs[j])*0.5);
if (VectorLength(eorg) > rad)
continue;
return ent;
}
return NULL;
}
Ich habe diese Funktion nicht geschrieben, sie stammt noch aus Q2 Zeiten
und wurde im Laufe ihres Lebens oft überarbeitet. Was tut sie genau
? Sie iteriert über alle Entities (sofern kein Anfangswert übergeben
wird), und ermittelt die Distanz zwischen der Entity und dem übergebenen
Ortsvektor. Ist die Distanz kleiner als der übergebene Radius wird
die Schleife verlassen und die ermittelte Entity zurückgegeben.
Der Prototyp für findradius gehört in g_local.h
am besten in Nähe der restlichen utils-funktionen (Z 475):
void AddRemap(const char *oldShader, const char *newShader, float timeOffset);
const char *BuildShaderStateConfig();
gentity_t *findradius (gentity_t *ent, vec3_t org, float rad);
2. Der Staubsauger
Jetzt folgt der schwierige Teil, die think Funktion der grenade. Öffne
g_missile.c und füge oberhalb von fire_plasma folgende Funktion
ein(Z 490):
/*
=================
G_Suck
=================
*/
static void G_Suck( gentity_t *self ) {
gentity_t *target;
vec3_t start,dir,end;
target = NULL;
// für alle Entitys innerhalb des Radius 500
while ((target = findradius(target, self->r.currentOrigin, 500)) != NULL)
{
// die grenade selbst zählt nicht
if (target == self)
continue;
// Entity muss ein Client sein
if (!target->client)
continue;
// Entity darf nicht der Spieler sein, der die gren erzeugt hat
if (target == self->parent)
continue;
// Entity muss Schaden nehmen können
if (!target->takedamage)
continue;
VectorCopy(target->r.currentOrigin, start);
VectorCopy(self->r.currentOrigin, end);
// Vektor zwischen grenade und ermittelter Entity (ziel) in dir speichern
VectorSubtract(end, start, dir);
VectorNormalize(dir);
// den Vektor auf 200 Einheiten skalieren und der Geschwindigkeit des Ziels zufügen
VectorScale(dir,200, target->client->ps.velocity);
}
self->nextthink = level.time + 40;
// nach x Millisek. explodieren (wir werden wait auf 20 sek setzen)
if (level.time > self->wait)
G_ExplodeMissile( self);
}
Kurz gesagt: diese Funktion holt sich alle Entities innerhalb des Radius
500, siebt diejenigen aus, die sie verschonen will, und saugt alle anderen
langsam aber stetig ein. Um das Testen zu erleichtern, solltest du die
Anweisung
if (target == self->parent)
continue;
auskommentieren. Dadurch wirken deine grenades auch auf dich. Da sie
aber bei deiner Berührung nicht explodieren, solltest du dir den Befehl
"kill" auf eine Taste binden.
3. Der Mann am Hebel
Fehlt nur noch jemand, der unsere schöne Funktion aufruft. fire_grenade
hat das Zeug dazu. Fast am Anfang dieser Funktion findest du folgende
Zeilen(Z 675):
bolt = G_Spawn();
bolt->classname = "grenade";
bolt->nextthink = level.time + 2500;
bolt->think = G_ExplodeMissile;
Ersetze die letzen beiden Zeilen durch folgende drei:
bolt = G_Spawn();
bolt->classname = "grenade";
bolt->nextthink = level.time + 1000; // ruft G_Suck in 1 sekunde
bolt->think = G_Suck; // setzt unsere G_Suck als think Funtion
bolt->wait = level.time + 20000; // Lebensdauer der grenade == 20 sek
Das war schon alles. Beim testen wird dir auffallen, dass der Ansaugeffekt
nicht sehr ausgereift ist. Um eine bessere Version zu erstellen, solltest
du das Tutorial Vortex Grenades II durcharbeiten.
<<
Tutorial 10 | | Tutorial
12 >>
|