📄 g_ctf.c
字号:
VectorScale (forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
if (ent->client->silencer_shots)
volume = 0.2;
gi.sound (ent, CHAN_RELIABLE+CHAN_WEAPON, gi.soundindex("weapons/grapple/grfire.wav"), volume, ATTN_NORM, 0);
CTFFireGrapple (ent, start, forward, damage, CTF_GRAPPLE_SPEED, effect);
#if 0
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_BLASTER);
gi.multicast (ent->s.origin, MULTICAST_PVS);
#endif
PlayerNoise(ent, start, PNOISE_WEAPON);
}
void CTFWeapon_Grapple_Fire (edict_t *ent)
{
int damage;
damage = 10;
CTFGrappleFire (ent, vec3_origin, damage, 0);
ent->client->ps.gunframe++;
}
void CTFWeapon_Grapple (edict_t *ent)
{
static int pause_frames[] = {10, 18, 27, 0};
static int fire_frames[] = {6, 0};
int prevstate;
// if the the attack button is still down, stay in the firing frame
if ((ent->client->buttons & BUTTON_ATTACK) &&
ent->client->weaponstate == WEAPON_FIRING &&
ent->client->ctf_grapple)
ent->client->ps.gunframe = 9;
if (!(ent->client->buttons & BUTTON_ATTACK) &&
ent->client->ctf_grapple) {
CTFResetGrapple(ent->client->ctf_grapple);
if (ent->client->weaponstate == WEAPON_FIRING)
ent->client->weaponstate = WEAPON_READY;
}
if (ent->client->newweapon &&
ent->client->ctf_grapplestate > CTF_GRAPPLE_STATE_FLY &&
ent->client->weaponstate == WEAPON_FIRING) {
// he wants to change weapons while grappled
ent->client->weaponstate = WEAPON_DROPPING;
ent->client->ps.gunframe = 32;
}
prevstate = ent->client->weaponstate;
Weapon_Generic (ent, 5, 9, 31, 36, pause_frames, fire_frames,
CTFWeapon_Grapple_Fire);
// if we just switched back to grapple, immediately go to fire frame
if (prevstate == WEAPON_ACTIVATING &&
ent->client->weaponstate == WEAPON_READY &&
ent->client->ctf_grapplestate > CTF_GRAPPLE_STATE_FLY) {
if (!(ent->client->buttons & BUTTON_ATTACK))
ent->client->ps.gunframe = 9;
else
ent->client->ps.gunframe = 5;
ent->client->weaponstate = WEAPON_FIRING;
}
}
void CTFTeam_f (edict_t *ent)
{
char *t, *s;
int desired_team;
t = gi.args();
if (!*t) {
gi.cprintf(ent, PRINT_HIGH, "You are on the %s team.\n",
CTFTeamName(ent->client->resp.ctf_team));
return;
}
if (ctfgame.match > MATCH_SETUP) {
gi.cprintf(ent, PRINT_HIGH, "Can't change teams in a match.\n");
return;
}
if (Q_stricmp(t, "red") == 0)
desired_team = CTF_TEAM1;
else if (Q_stricmp(t, "blue") == 0)
desired_team = CTF_TEAM2;
else {
gi.cprintf(ent, PRINT_HIGH, "Unknown team %s.\n", t);
return;
}
if (ent->client->resp.ctf_team == desired_team) {
gi.cprintf(ent, PRINT_HIGH, "You are already on the %s team.\n",
CTFTeamName(ent->client->resp.ctf_team));
return;
}
////
ent->svflags = 0;
ent->flags &= ~FL_GODMODE;
ent->client->resp.ctf_team = desired_team;
ent->client->resp.ctf_state = 0;
s = Info_ValueForKey (ent->client->pers.userinfo, "skin");
CTFAssignSkin(ent, s);
if (ent->solid == SOLID_NOT) { // spectator
PutClientInServer (ent);
// add a teleportation effect
ent->s.event = EV_PLAYER_TELEPORT;
// hold in place briefly
ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
ent->client->ps.pmove.pm_time = 14;
gi.bprintf(PRINT_HIGH, "%s joined the %s team.\n",
ent->client->pers.netname, CTFTeamName(desired_team));
return;
}
ent->health = 0;
player_die (ent, ent, ent, 100000, vec3_origin);
// don't even bother waiting for death frames
ent->deadflag = DEAD_DEAD;
respawn (ent);
ent->client->resp.score = 0;
gi.bprintf(PRINT_HIGH, "%s changed to the %s team.\n",
ent->client->pers.netname, CTFTeamName(desired_team));
}
/*
==================
CTFScoreboardMessage
==================
*/
void CTFScoreboardMessage (edict_t *ent, edict_t *killer)
{
char entry[1024];
char string[1400];
int len;
int i, j, k, n;
int sorted[2][MAX_CLIENTS];
int sortedscores[2][MAX_CLIENTS];
int score, total[2], totalscore[2];
int last[2];
gclient_t *cl;
edict_t *cl_ent;
int team;
int maxsize = 1000;
// sort the clients by team and score
total[0] = total[1] = 0;
last[0] = last[1] = 0;
totalscore[0] = totalscore[1] = 0;
for (i=0 ; i<game.maxclients ; i++)
{
cl_ent = g_edicts + 1 + i;
if (!cl_ent->inuse)
continue;
if (game.clients[i].resp.ctf_team == CTF_TEAM1)
team = 0;
else if (game.clients[i].resp.ctf_team == CTF_TEAM2)
team = 1;
else
continue; // unknown team?
score = game.clients[i].resp.score;
for (j=0 ; j<total[team] ; j++)
{
if (score > sortedscores[team][j])
break;
}
for (k=total[team] ; k>j ; k--)
{
sorted[team][k] = sorted[team][k-1];
sortedscores[team][k] = sortedscores[team][k-1];
}
sorted[team][j] = i;
sortedscores[team][j] = score;
totalscore[team] += score;
total[team]++;
}
// print level name and exit rules
// add the clients in sorted order
*string = 0;
len = 0;
// team one
sprintf(string, "if 24 xv 8 yv 8 pic 24 endif "
"xv 40 yv 28 string \"%4d/%-3d\" "
"xv 98 yv 12 num 2 18 "
"if 25 xv 168 yv 8 pic 25 endif "
"xv 200 yv 28 string \"%4d/%-3d\" "
"xv 256 yv 12 num 2 20 ",
totalscore[0], total[0],
totalscore[1], total[1]);
len = strlen(string);
for (i=0 ; i<16 ; i++)
{
if (i >= total[0] && i >= total[1])
break; // we're done
#if 0 //ndef NEW_SCORE
// set up y
sprintf(entry, "yv %d ", 42 + i * 8);
if (maxsize - len > strlen(entry)) {
strcat(string, entry);
len = strlen(string);
}
#else
*entry = 0;
#endif
// left side
if (i < total[0]) {
cl = &game.clients[sorted[0][i]];
cl_ent = g_edicts + 1 + sorted[0][i];
#if 0 //ndef NEW_SCORE
sprintf(entry+strlen(entry),
"xv 0 %s \"%3d %3d %-12.12s\" ",
(cl_ent == ent) ? "string2" : "string",
cl->resp.score,
(cl->ping > 999) ? 999 : cl->ping,
cl->pers.netname);
if (cl_ent->client->pers.inventory[ITEM_INDEX(flag2_item)])
strcat(entry, "xv 56 picn sbfctf2 ");
#else
sprintf(entry+strlen(entry),
"ctf 0 %d %d %d %d ",
42 + i * 8,
sorted[0][i],
cl->resp.score,
cl->ping > 999 ? 999 : cl->ping);
if (cl_ent->client->pers.inventory[ITEM_INDEX(flag2_item)])
sprintf(entry + strlen(entry), "xv 56 yv %d picn sbfctf2 ",
42 + i * 8);
#endif
if (maxsize - len > strlen(entry)) {
strcat(string, entry);
len = strlen(string);
last[0] = i;
}
}
// right side
if (i < total[1]) {
cl = &game.clients[sorted[1][i]];
cl_ent = g_edicts + 1 + sorted[1][i];
#if 0 //ndef NEW_SCORE
sprintf(entry+strlen(entry),
"xv 160 %s \"%3d %3d %-12.12s\" ",
(cl_ent == ent) ? "string2" : "string",
cl->resp.score,
(cl->ping > 999) ? 999 : cl->ping,
cl->pers.netname);
if (cl_ent->client->pers.inventory[ITEM_INDEX(flag1_item)])
strcat(entry, "xv 216 picn sbfctf1 ");
#else
sprintf(entry+strlen(entry),
"ctf 160 %d %d %d %d ",
42 + i * 8,
sorted[1][i],
cl->resp.score,
cl->ping > 999 ? 999 : cl->ping);
if (cl_ent->client->pers.inventory[ITEM_INDEX(flag1_item)])
sprintf(entry + strlen(entry), "xv 216 yv %d picn sbfctf1 ",
42 + i * 8);
#endif
if (maxsize - len > strlen(entry)) {
strcat(string, entry);
len = strlen(string);
last[1] = i;
}
}
}
// put in spectators if we have enough room
if (last[0] > last[1])
j = last[0];
else
j = last[1];
j = (j + 2) * 8 + 42;
k = n = 0;
if (maxsize - len > 50) {
for (i = 0; i < maxclients->value; i++) {
cl_ent = g_edicts + 1 + i;
cl = &game.clients[i];
if (!cl_ent->inuse ||
cl_ent->solid != SOLID_NOT ||
cl_ent->client->resp.ctf_team != CTF_NOTEAM)
continue;
if (!k) {
k = 1;
sprintf(entry, "xv 0 yv %d string2 \"Spectators\" ", j);
strcat(string, entry);
len = strlen(string);
j += 8;
}
sprintf(entry+strlen(entry),
"ctf %d %d %d %d %d ",
(n & 1) ? 160 : 0, // x
j, // y
i, // playernum
cl->resp.score,
cl->ping > 999 ? 999 : cl->ping);
if (maxsize - len > strlen(entry)) {
strcat(string, entry);
len = strlen(string);
}
if (n & 1)
j += 8;
n++;
}
}
if (total[0] - last[0] > 1) // couldn't fit everyone
sprintf(string + strlen(string), "xv 8 yv %d string \"..and %d more\" ",
42 + (last[0]+1)*8, total[0] - last[0] - 1);
if (total[1] - last[1] > 1) // couldn't fit everyone
sprintf(string + strlen(string), "xv 168 yv %d string \"..and %d more\" ",
42 + (last[1]+1)*8, total[1] - last[1] - 1);
gi.WriteByte (svc_layout);
gi.WriteString (string);
}
/*------------------------------------------------------------------------*/
/* TECH */
/*------------------------------------------------------------------------*/
void CTFHasTech(edict_t *who)
{
if (level.time - who->client->ctf_lasttechmsg > 2) {
gi.centerprintf(who, "You already have a TECH powerup.");
who->client->ctf_lasttechmsg = level.time;
}
}
gitem_t *CTFWhat_Tech(edict_t *ent)
{
gitem_t *tech;
int i;
i = 0;
while (tnames[i]) {
if ((tech = FindItemByClassname(tnames[i])) != NULL &&
ent->client->pers.inventory[ITEM_INDEX(tech)]) {
return tech;
}
i++;
}
return NULL;
}
qboolean CTFPickup_Tech (edict_t *ent, edict_t *other)
{
gitem_t *tech;
int i;
i = 0;
while (tnames[i]) {
if ((tech = FindItemByClassname(tnames[i])) != NULL &&
other->client->pers.inventory[ITEM_INDEX(tech)]) {
CTFHasTech(other);
return false; // has this one
}
i++;
}
// client only gets one tech
other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
other->client->ctf_regentime = level.time;
return true;
}
static void SpawnTech(gitem_t *item, edict_t *spot);
static edict_t *FindTechSpawn(void)
{
edict_t *spot = NULL;
int i = rand() % 16;
while (i--)
spot = G_Find (spot, FOFS(classname), "info_player_deathmatch");
if (!spot)
spot = G_Find (spot, FOFS(classname), "info_player_deathmatch");
return spot;
}
static void TechThink(edict_t *tech)
{
edict_t *spot;
if ((spot = FindTechSpawn()) != NULL) {
SpawnTech(tech->item, spot);
G_FreeEdict(tech);
} else {
tech->nextthink = level.time + CTF_TECH_TIMEOUT;
tech->think = TechThink;
}
}
void CTFDrop_Tech(edict_t *ent, gitem_t *item)
{
edict_t *tech;
tech = Drop_Item(ent, item);
tech->nextthink = level.time + CTF_TECH_TIMEOUT;
tech->think = TechThink;
ent->client->pers.inventory[ITEM_INDEX(item)] = 0;
}
void CTFDeadDropTech(edict_t *ent)
{
gitem_t *tech;
edict_t *dropped;
int i;
i = 0;
while (tnames[i]) {
if ((tech = FindItemByClassname(tnames[i])) != NULL &&
ent->client->pers.inventory[ITEM_INDEX(tech)]) {
dropped = Drop_Item(ent, tech);
// hack the velocity to make it bounce random
dropped->velocity[0] = (rand() % 600) - 300;
dropped->velocity[1] = (rand() % 600) - 300;
dropped->nextthink = level.time + CTF_TECH_TIMEOUT;
dropped->think = TechThink;
dropped->owner = NULL;
ent->client->pers.inventory[ITEM_INDEX(tech)] = 0;
}
i++;
}
}
static void SpawnTech(gitem_t *item, edict_t *spot)
{
edict_t *ent;
vec3_t forward, right;
vec3_t angles;
ent = G_Spawn();
ent->classname = item->classname;
ent->item = item;
ent->spawnflags = DROPPED_ITEM;
ent->s.effects = item->world_model_flags;
ent->s.renderfx = RF_GLOW;
VectorSet (ent->mins, -15, -15, -15);
VectorSet (ent->maxs, 15, 15, 15);
gi.setmodel (ent, ent->item->world_model);
ent->solid = SOLID_TRIGGER;
ent->movetype = MOVETYPE_TOSS;
ent->touch = Touch_Item;
ent->owner = ent;
angles[0] = 0;
angles[1] = rand() % 360;
angles[2] = 0;
AngleVectors (angles, forward, right, NULL);
VectorCopy (spot->s.origin, ent->s.origin);
ent->s.origin[2] += 16;
VectorScale (forward, 100, ent->velocity);
ent->velocity[2] = 300;
ent->nextthink = level.time + CTF_TECH_TIMEOUT;
ent->think = TechThink;
gi.linkentity (ent);
}
static void SpawnTechs(edict_t *ent)
{
gitem_t *tech;
edict_t *spot;
int i;
i = 0;
while (tnames[i]) {
if ((tech = FindItemByClassname(tnames[i])) != NULL &&
(spot = FindTechSpawn()) != NULL)
SpawnTech(tech, spot);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -