|
Alright,
here it is... i spent about 4 hours today with this thing (5 mins on the code
the rest playtesting it, cuz it was oh so much fun...
the Quake1 thunderbolt. YumNum! the damage is all adjustable, fuzzysteve had
made a comment about the discharge damage but, i didnt have a chance to
actually give him the real REASON its so high. .. because its a radius, if
its NOT, as high as it is, you dont die when you discharge if you have 200
armor. so, too bad i say! =)
also, the tutorial is in zipform as a link down at the bottom here. the zip
contains the 2 models, 2 wavs i borrowed(ripped?) from q1 and rogue, and an
icon i made from scatch in ab out 5 seconds. (well thats exagerration, but it
didnt take long for the piece of crap that it is =))
anyway, on with the instructions/tutorial, or whateevr you wanna call it =)
/*
Thunderbolt Tutorial/instructions for Quake2.
Uses TE_LIGHTNING for the effect.
120% as good as the original (lacking the original view model of course)
Written by Omega Maelstrom. omega@mmxq2tc.cjb.net
Build Time: 5 mins for working code, off and on, 4 hours play testing
with friends=)
What you will need: tut-tbolt_omega.zip (you wont *NEED* this, but it
helps. because its the graphics/sounds *I* used/ripped <grin> for it,
as well as the c/header files i modified for this.
i wrote this whole thing in DOS Edit, and built it In LCC. (yes, as
you've seen by my other posts, i do use MSVC usually,. but for this
lcc is just damned quicker.
legend:
*** denotes first step
** denotes sub-steps inbetween
=== denotes the END of a section
==== denotes the end of a step
*/
Part 1:
***open up g_local.h and add the following:
**find the MeansOfDeath defines, and add these.
//OM-LGUN
#define MOD_TBOLT 34
#define MOD_TBOLT_WATER 35
#define MOD_TBOLT_DISCHARGE 36
//OM-LGUN-END
**then scroll down to the prototypes for g_utils.c (just search for g_utils.c
and add at the end after vectoangles:
//OM-LGUN
void vectoangles2 (vec3_t vec, vec3_t angles);
//OM-LGUN-END
**now find the rest of the weapon defines and add
//OM-LGUN
#define WEAP_TBOLT 12 // or whatever your last free # is
//OM-LGUN-END
**now jump to the *END* of the file, (best place for them) and add the following:
//OM-LGUN
#define TBOLT_DAMAGE 20
#define TBOLT_CELLS 1
//OM-LGUN-END
===end of g_local.h===
***next, open up g_items.c
**add
//OM-LGUN
void Weapon_Thunderbolt (edict_t *ent);
//OM-LGUN-END
after the BFG (or whatever your last weapon is)
**now add this item after the bfg, or somewhere in your items list.
//OM-LGUN
/*QUAKED weapon_thunderbolt (.3 .3 1) (-16 -16 -16) (16 16 16)
*/
{
"weapon_thunderbolt",
Pickup_Weapon,
Use_Weapon,
Drop_Weapon,
Weapon_Thunderbolt,
"misc/w_pkup.wav",
"models/weapons/g_hyperb/tris.md2", EF_ROTATE,
"models/weapons/v_hyperb/tris.md2",
"w_tbolt",
"Thunderbolt",
0,
TBOLT_CELLS,
"Cells",
IT_WEAPON|IT_STAY_COOP,
WEAP_TBOLT,
NULL,
0,
"weapons/tesla.wav weapons/lstart.wav models/proj/lightning/tris.md2"
},
//OM-LGUN-END
===end of g_items.c===
***next, open up g_utils.c
**paste the following two functions in. (replace the old vectoangles)
//OM-LGUN
//NEW vectoangles plus vectoangles2, from rogue source )fixes a bug and adds
//something new.
void vectoangles (vec3_t value1, vec3_t angles)
{
float forward;
float yaw, pitch;
if (value1[1] == 0 && value1[0] == 0)
{
yaw = 0;
if (value1[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
// PMM - fixed to correct for pitch of 0
if (value1[0])
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
else if (value1[1] > 0)
yaw = 90;
else
yaw = 270;
if (yaw < 0)
yaw += 360;
forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
angles[PITCH] = -pitch;
angles[YAW] = yaw;
angles[ROLL] = 0;
}
void vectoangles2 (vec3_t value1, vec3_t angles)
{
float forward;
float yaw, pitch;
if (value1[1] == 0 && value1[0] == 0)
{
yaw = 0;
if (value1[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
// PMM - fixed to correct for pitch of 0
if (value1[0])
yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
else if (value1[1] > 0)
yaw = 90;
else
yaw = 270;
if (yaw < 0)
yaw += 360;
forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
pitch = (atan2(value1[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
angles[PITCH] = -pitch;
angles[YAW] = yaw;
angles[ROLL] = 0;
}
===end g_utils.c===
***next, open up g_weapon.c
**add the following code at the end:
//OM-LGUN
void fire_lightning (edict_t *self, vec3_t start, vec3_t aimdir, int damage)
{
vec3_t from;
vec3_t end;
vec3_t dir;
vec3_t forward, right, up;
trace_t tr;
int mask;
edict_t *tmpobj;
vectoangles2 (aimdir, dir);
AngleVectors (dir, forward, right, up);
VectorMA (start, 8192, forward, end);
mask = MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA|CONTENTS_WATER;
tr = gi.trace (start, NULL, NULL, end, self, mask);
if (tr.contents & (CONTENTS_SLIME|CONTENTS_LAVA|CONTENTS_WATER))
{
tmpobj = G_Spawn();
VectorCopy (tr.endpos, tmpobj->s.origin);
tmpobj->movetype = MOVETYPE_NONE;
tmpobj->solid = SOLID_NOT;
tmpobj->classname = "tmpobject";
tmpobj->s.modelindex = 0;
tmpobj->nextthink = level.time + 0.01;
tmpobj->think = G_FreeEdict;
gi.linkentity (tmpobj);
T_RadiusDamage(tmpobj, self, damage*2, NULL, damage*4, MOD_TBOLT_WATER);
}
else
{
if ((tr.ent != self) && (tr.ent->takedamage))
T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, damage, 0, MOD_TBOLT);
}
// make the lightning bolt from the gun to the wall. (cute huh?)
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_LIGHTNING);
gi.WriteShort (tr.ent - g_edicts);
gi.WriteShort (self - g_edicts);
gi.WritePosition (tr.endpos);
gi.WritePosition (start);
gi.multicast (start, MULTICAST_PVS);
// spawn some sparks at the destination (go sparky go!)
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_WELDING_SPARKS);
gi.WriteByte (15);
gi.WritePosition (tr.endpos);
gi.WriteDir (vec3_origin);
gi.WriteByte (0xB2 + (rand()&3));
gi.multicast (tr.endpos, MULTICAST_PVS);
if (self->client)
PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
}
//OM-LGUN-END
===end g_weapon.c===
***open up p_weapon.c
**paste the following code at the end of the file. (easy shiz eh?)
//OM-LGUN
void Weapon_Thunderbolt_Fire (edict_t *ent)
{
vec3_t offset, start;
vec3_t forward, right;
int ammo;
int damage;
int toasty;
if (!(ent->client->buttons & BUTTON_ATTACK))
{
ent->client->ps.gunframe++;
}
else
{
if (! ent->client->pers.inventory[ent->client->ammo_index] )
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
}
else
{
damage = TBOLT_DAMAGE;
if (is_quad) {
toasty = 8000;
damage *= 4;
}
else
toasty = 2000;
if (ent->client->ps.gunframe == 6) // if its starting. do the initial bolt sound
gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/lfire.wav"), 1, ATTN_NORM, 0);
gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/tesla.wav"), .5, ATTN_NORM, 0);
if (ent->waterlevel == 3) //ZZZZZZZZZAAAAAAAAAAAAAAAPPPPPPP!!!!!!
{
ent->client->pers.inventory[ent->client->ammo_index] = 0;
T_RadiusDamage(ent, ent, toasty, NULL, toasty, MOD_TBOLT_DISCHARGE);
return;
}
AngleVectors (ent->client->v_angle, forward, right, NULL);
VectorScale (forward, -2, ent->client->kick_origin);
VectorSet(offset, 8, 8, ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
fire_lightning (ent, start, forward, damage);
PlayerNoise(ent, start, PNOISE_WEAPON);
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index] -= TBOLT_CELLS;
}
}
ent->client->ps.gunframe++;
if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
ent->client->ps.gunframe = 7;
}
void Weapon_Thunderbolt (edict_t *ent)
{
static int pause_frames[] = {0};
static int fire_frames[] = {6, 7, 8, 9, 10, 11};
Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_Thunderbolt_Fire);
}
//OM-LGUN-END
===end p_weapon.c===
***for one of the final steps, load up p_client.c
**now find the obituaries, and add these reqpectively
**under if attacker = self ...
//OM-LGUN
case MOD_TBOLT_DISCHARGE:
message = "made a shocking mistake";
break;
case MOD_TBOLT_WATER:
message = "feels the tingle from the electrified liquid";
break;
**attacker && attacker->client
//OM-LGUN
case MOD_TBOLT:
message = "accepts";
message2 = "'s shaft";
break;
case MOD_TBOLT_WATER:
message = "feels the tingle from";
message2 = "'s water shock";
break;
case MOD_TBOLT_DISCHARGE:
message = "suffers the extreme pain of";
message2 = "'s suicidal discharge";
break;
//OM-LGUN-END
===end p_client.c===
====end Step #1====
Step 2: rebuild.
====end Step #2====
Step 3: Play.Frag.Kill.Fry.Shock.you know.
====end Step #3====
that should be about it.
if you have any questions, email me.
-Omega
|