void Weapon_Perforator (edict_t *ent){ static int pause_frames[] = {25, 33, 42, 50, 0}; static int fire_frames[] = {5, 0}; Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_Perforator_Fire);}
Yes, the function is in perforator.c.I`m not sure how I should rebuild it, though. If a prototype is not a definition, then which file should I look into to add the actual definition for Weapon_Perforator?It has been a great learning experience I must admit. Thanks for all your support so far.
void Weapon_Perforator (edict_t *ent);
/*** perforator.h* **///#include "g_local.h"#ifndef PERFORATOR_H#define PERFORATOR_Hvoid Weapon_Perforator_Fire (edict_t *ent);void Weapon_Perforator (edict_t *ent);void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick);#endif---
/*** perforator.c**/#include "perforator.h"/*======================================================================PERFORATOR======================================================================*/void Weapon_Perforator_Fire (edict_t *ent){ vec3_t offset, start; vec3_t forward, right; int damage; int kick; damage = 50; kick = 400; if (is_quad) { damage *= 4; } AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_perforator (ent, start, forward, damage, 650, kick); // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_RAILGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--;}void Weapon_Perforator (edict_t *ent){ static int pause_frames[] = {25, 33, 42, 50, 0}; static int fire_frames[] = {5, 0}; Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_Perforator_Fire);}/*=================perforator_touch=================*/void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf){ vec3_t origin; int n; if (other == ent->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (ent); return; } if (ent->owner->client) PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); // calculate position for the explosion entity VectorMA (ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_PERFORATOR); } else { // don't throw any debris in net games if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) { n = rand() % 5; while(n--) ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_PERFORATOR); gi.WriteByte (svc_temp_entity); if (ent->waterlevel) gi.WriteByte (TE_PERFORATOR_EXPLOSION_WATER); else gi.WriteByte (TE_PERFORATOR_EXPLOSION); gi.WritePosition (origin); gi.multicast (ent->s.origin, MULTICAST_PHS); G_FreeEdict (ent);}/*=================fire_perforator=================*/void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick){ edict_t *perforator; perforator = G_Spawn(); VectorCopy (start, perforator->s.origin); VectorCopy (dir, perforator->movedir); vectoangles (dir, perforator->s.angles); VectorScale (dir, speed, perforator->velocity); perforator->movetype = MOVETYPE_FLYMISSILE; perforator->clipmask = MASK_SHOT; perforator->solid = SOLID_BBOX; perforator->s.effects |= EF_ROCKET; VectorClear (perforator->mins); VectorClear (perforator->maxs); perforator->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); perforator->owner = self; perforator->touch = perforator_touch; perforator->nextthink = level.time + 8000/speed; perforator->think = G_FreeEdict; perforator->dmg = damage; perforator->s.sound = gi.soundindex ("weapons/rockfly.wav"); perforator->classname = "perforator"; if (self->client) check_dodge (self, perforator->s.origin, dir, speed); gi.linkentity (perforator);}
/*QUAKED key_yellow_key (0 .5 .8) (-16 -16 -16) (16 16 16)normal door key - yellow*/ { "key_yellow_key", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/yellow_key/tris.md2", EF_ROTATE, NULL, "k_yellowkey", "Yellow Key", 2, 0, NULL, IT_STAY_COOP|IT_KEY, 0, NULL, 0,/* precache */ "" },
/*QUAKED key_explosive_charges (0 .5 .8) (-16 -16 -16) (16 16 16)explosive charges*/ { "key_explosive_charges", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/charges/tris.md2", EF_ROTATE, NULL, "k_charges", "Explosive Charges", 2, 0, NULL, IT_STAY_COOP|IT_KEY, 0, NULL, 0,/* precache */ "" },
Yes, the prototype and definition are in perforator.h: (yes I made the perforator files, like you mentioned earlier)Code: [Select]/***Â perforator.h*Â **///#include "g_local.h"#ifndef PERFORATOR_H#define PERFORATOR_Hvoid Weapon_Perforator_Fire (edict_t *ent);void Weapon_Perforator (edict_t *ent);void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick);#endif---
/***Â perforator.h*Â **///#include "g_local.h"#ifndef PERFORATOR_H#define PERFORATOR_Hvoid Weapon_Perforator_Fire (edict_t *ent);void Weapon_Perforator (edict_t *ent);void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick);#endif---
Also, here is my perforator.c file:
Code: [Select]/***Â perforator.c**/#include "perforator.h"/*======================================================================PERFORATOR======================================================================*/void Weapon_Perforator_Fire (edict_t *ent){ vec3_t offset, start; vec3_t forward, right; int damage; int kick; damage = 50; kick = 400; if (is_quad) { damage *= 4; } AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_perforator (ent, start, forward, damage, 650, kick); // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_RAILGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--;}void Weapon_Perforator (edict_t *ent){ static int pause_frames[] = {25, 33, 42, 50, 0}; static int fire_frames[] = {5, 0}; Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_Perforator_Fire);}/*=================perforator_touch=================*/void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf){ vec3_t origin; int n; if (other == ent->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (ent); return; } if (ent->owner->client) PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); // calculate position for the explosion entity VectorMA (ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_PERFORATOR); } else { // don't throw any debris in net games if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) { n = rand() % 5; while(n--) ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_PERFORATOR); gi.WriteByte (svc_temp_entity); if (ent->waterlevel) gi.WriteByte (TE_PERFORATOR_EXPLOSION_WATER); else gi.WriteByte (TE_PERFORATOR_EXPLOSION); gi.WritePosition (origin); gi.multicast (ent->s.origin, MULTICAST_PHS); G_FreeEdict (ent);}/*=================fire_perforator=================*/void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick){ edict_t *perforator; perforator = G_Spawn(); VectorCopy (start, perforator->s.origin); VectorCopy (dir, perforator->movedir); vectoangles (dir, perforator->s.angles); VectorScale (dir, speed, perforator->velocity); perforator->movetype = MOVETYPE_FLYMISSILE; perforator->clipmask = MASK_SHOT; perforator->solid = SOLID_BBOX; perforator->s.effects |= EF_ROCKET; VectorClear (perforator->mins); VectorClear (perforator->maxs); perforator->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); perforator->owner = self; perforator->touch = perforator_touch; perforator->nextthink = level.time + 8000/speed; perforator->think = G_FreeEdict; perforator->dmg = damage; perforator->s.sound = gi.soundindex ("weapons/rockfly.wav"); perforator->classname = "perforator"; if (self->client) check_dodge (self, perforator->s.origin, dir, speed); gi.linkentity (perforator);}Slightly unrelated note: I managed to add two new key entities to the game, one of them being a yellow key. The yellow key uses the model from the red / blue keys but a new skin. It`s located in models/items/keys/yellow_key. Like all other skins it uses the name "skin.pcx". It also has a tris.md2 in the same folder, like the other keys (copied it from the red / blue key) However, despite the fact that I "followed all the rules" when I go to drop the key through console it shows up as a plain red skinned key. Why? Here is the code for my new key btw: (the code works properly, it`s just the skin not showing up)Code: [Select]/*QUAKED key_yellow_key (0 .5 .8) (-16 -16 -16) (16 16 16)normal door key - yellow*/ { "key_yellow_key", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/yellow_key/tris.md2", EF_ROTATE, NULL, "k_yellowkey", "Yellow Key", 2, 0, NULL, IT_STAY_COOP|IT_KEY, 0, NULL, 0,/* precache */ "" },The other new key I made was a set of explosive charges. This time I took a model from the Rogue mission pack, the tag token. They accidentally named their skin "skin1.pcx" instead of "skin.pcx" for some reasons, so for compatibility I renamed it without the 1. I put it in models/items/keys/charges/ and have both tris.md2 and the skin.pcx in there, but once again it just drops a red-skinned key (though it still says explosive charges when I pick it up, so the code works) when I type "drop explosive charges". Here`s the code again:Code: [Select]/*QUAKED key_explosive_charges (0 .5 .8) (-16 -16 -16) (16 16 16)explosive charges*/ { "key_explosive_charges", Pickup_Key, NULL, Drop_General, NULL, "items/pkup.wav", "models/items/keys/charges/tris.md2", EF_ROTATE, NULL, "k_charges", "Explosive Charges", 2, 0, NULL, IT_STAY_COOP|IT_KEY, 0, NULL, 0,/* precache */ "" },Thanks in advance.
/***Â perforator.c**/#include "perforator.h"/*======================================================================PERFORATOR======================================================================*/void Weapon_Perforator_Fire (edict_t *ent){ vec3_t offset, start; vec3_t forward, right; int damage; int kick; damage = 50; kick = 400; if (is_quad) { damage *= 4; } AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_perforator (ent, start, forward, damage, 650, kick); // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_RAILGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--;}void Weapon_Perforator (edict_t *ent){ static int pause_frames[] = {25, 33, 42, 50, 0}; static int fire_frames[] = {5, 0}; Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_Perforator_Fire);}/*=================perforator_touch=================*/void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf){ vec3_t origin; int n; if (other == ent->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (ent); return; } if (ent->owner->client) PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); // calculate position for the explosion entity VectorMA (ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_PERFORATOR); } else { // don't throw any debris in net games if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) { n = rand() % 5; while(n--) ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_PERFORATOR); gi.WriteByte (svc_temp_entity); if (ent->waterlevel) gi.WriteByte (TE_PERFORATOR_EXPLOSION_WATER); else gi.WriteByte (TE_PERFORATOR_EXPLOSION); gi.WritePosition (origin); gi.multicast (ent->s.origin, MULTICAST_PHS); G_FreeEdict (ent);}/*=================fire_perforator=================*/void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick){ edict_t *perforator; perforator = G_Spawn(); VectorCopy (start, perforator->s.origin); VectorCopy (dir, perforator->movedir); vectoangles (dir, perforator->s.angles); VectorScale (dir, speed, perforator->velocity); perforator->movetype = MOVETYPE_FLYMISSILE; perforator->clipmask = MASK_SHOT; perforator->solid = SOLID_BBOX; perforator->s.effects |= EF_ROCKET; VectorClear (perforator->mins); VectorClear (perforator->maxs); perforator->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); perforator->owner = self; perforator->touch = perforator_touch; perforator->nextthink = level.time + 8000/speed; perforator->think = G_FreeEdict; perforator->dmg = damage; perforator->s.sound = gi.soundindex ("weapons/rockfly.wav"); perforator->classname = "perforator"; if (self->client) check_dodge (self, perforator->s.origin, dir, speed); gi.linkentity (perforator);}
How come even though the function is clearly referred to in perforator.c, as shown above, it refuses to compile
/*** perforator.h* **/#ifndef PERFORATOR_H#define PERFORATOR_Hvoid Weapon_Perforator_Fire (edict_t *ent);void Weapon_Perforator (edict_t *ent);void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick);#endif
/*** perforator.c**/#include "g_items.c"#include "g_local.h"#include "perforator.h"/*======================================================================PERFORATOR======================================================================*/void Weapon_Perforator_Fire (edict_t *ent){ vec3_t offset, start; vec3_t forward, right; int damage; int kick; damage = 50; kick = 400; if (is_quad) { damage *= 4; } AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_perforator (ent, start, forward, damage, 650, kick); // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_RAILGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--;}void Weapon_Perforator (edict_t *ent){ static int pause_frames[] = {25, 33, 42, 50, 0}; static int fire_frames[] = {5, 0}; Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_Perforator_Fire);}/*=================perforator_touch=================*/void perforator_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf){ vec3_t origin; int n; if (other == ent->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (ent); return; } if (ent->owner->client) PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); // calculate position for the explosion entity VectorMA (ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_PERFORATOR); } else { // don't throw any debris in net games if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) { n = rand() % 5; while(n--) ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_PERFORATOR); gi.WriteByte (svc_temp_entity); if (ent->waterlevel) gi.WriteByte (TE_PERFORATOR_EXPLOSION_WATER); else gi.WriteByte (TE_PERFORATOR_EXPLOSION); gi.WritePosition (origin); gi.multicast (ent->s.origin, MULTICAST_PHS); G_FreeEdict (ent);}/*=================fire_perforator=================*/void fire_perforator (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick){ edict_t *perforator; perforator = G_Spawn(); VectorCopy (start, perforator->s.origin); VectorCopy (dir, perforator->movedir); vectoangles (dir, perforator->s.angles); VectorScale (dir, speed, perforator->velocity); perforator->movetype = MOVETYPE_FLYMISSILE; perforator->clipmask = MASK_SHOT; perforator->solid = SOLID_BBOX; perforator->s.effects |= EF_ROCKET; VectorClear (perforator->mins); VectorClear (perforator->maxs); perforator->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2"); perforator->owner = self; perforator->touch = perforator_touch; perforator->nextthink = level.time + 8000/speed; perforator->think = G_FreeEdict; perforator->dmg = damage; perforator->s.sound = gi.soundindex ("weapons/rockfly.wav"); perforator->classname = "perforator"; if (self->client) check_dodge (self, perforator->s.origin, dir, speed); gi.linkentity (perforator);}
Here it is again, maybe someone knows where I have went wrong?
1>------ Build started: Project: game, Configuration: Release Win32 ------1>Compiling...1>perforator.c1>.\perforator.c(38) : warning C4013: 'P_ProjectSource' undefined; assuming extern returning int1>.\perforator.c(60) : warning C4013: 'Weapon_Generic' undefined; assuming extern returning int1>.\perforator.c(116) : warning C4100: 'kick' : unreferenced formal parameter1>Linking...1> Creating library .\..\release/gamex86.lib and object .\..\release/gamex86.exp1>perforator.obj : error LNK2019: unresolved external symbol _check_dodge referenced in function _fire_perforator1>perforator.obj : error LNK2019: unresolved external symbol _P_ProjectSource referenced in function _Weapon_Perforator_Fire1>..\release\gamex86.dll : fatal error LNK1120: 2 unresolved externals1>Build log was saved at "file://f:\Quake 2 Folder\Source Code\quake2-3.21\game\intermediates\BuildLog.htm"1>game - 3 error(s), 3 warning(s)========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========