void p_medic_firebolt (edict_t *ent) { int min_dmg; int damage = MEDIC_BOLT_INITIAL_DMG+MEDIC_BOLT_ADDON_DMG*ent->myskills.abilities[MEDIC].current_level; int speed = MEDIC_BOLT_INITIAL_SPEED+MEDIC_BOLT_ADDON_SPEED*ent->myskills.abilities[MEDIC].current_level; vec3_t forward, right, start; // is this a firing frame? if (ent->s.frame != 188 && ent->s.frame != 185) return; // check for adequate ammo if (ent->myskills.abilities[MEDIC].ammo < MEDIC_BOLT_AMMO) return; ent->myskills.abilities[MEDIC].ammo -= MEDIC_BOLT_AMMO; AngleVectors(ent->client->v_angle, forward, right, NULL); G_ProjectSource(ent->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1], forward, right, start); min_dmg = floattoint(0.111*damage); damage = GetRandom(min_dmg, damage); fire_blaster(ent, start, forward, damage, speed, EF_BLASTER, BLASTER_PROJ_BLAST, MOD_BLASTER, 2.0, false); gi.WriteByte (svc_muzzleflash2); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ2_MEDIC_BLASTER_1); gi.multicast (start, MULTICAST_PVS); gi.sound (ent, CHAN_WEAPON, gi.soundindex("weapons/photon.wav"), 1, ATTN_NORM, 0); }
void p_medic_hb_regen (edict_t *ent, int regen_frames, int regen_delay) { int ammo; int max = ent->myskills.abilities[MEDIC].max_ammo; int *current = &ent->myskills.abilities[MEDIC].ammo; int *delay = &ent->myskills.abilities[MEDIC].ammo_regenframe; if (*current > max) return; // don't regenerate ammo if player is firing if ((ent->client->buttons & BUTTON_ATTACK) && (ent->client->weapon_mode != 1)) return; if (regen_delay > 0) { if (level.framenum < *delay) return; *delay = level.framenum + regen_delay; } else regen_delay = 1; ammo = floattoint((float)max / ((float)regen_frames / regen_delay)); if (ammo < 1) ammo = 1; *current += ammo; if (*current > max) *current = max; }
void p_medic_reanimate (edict_t *ent, edict_t *target) { int skill_level; vec3_t bmin, bmax; edict_t *e; skill_level = floattoint((1.0+MEDIC_RESURRECT_BONUS)*ent->myskills.abilities[MEDIC].current_level); if (!strcmp(target->classname, "drone") && (ent->num_monsters + target->monsterinfo.control_cost <= MAX_MONSTERS)) { target->monsterinfo.level = skill_level; M_SetBoundingBox(target->mtype, bmin, bmax); if (G_IsValidLocation(target, target->s.origin, bmin, bmax) && M_Initialize(ent, target)) { // restore this drone target->monsterinfo.slots_freed = false; // reset freed flag target->health = 0.33*target->max_health; target->monsterinfo.power_armor_power = 0.33*target->monsterinfo.max_armor; target->monsterinfo.resurrected_time = level.time + 2.0; target->activator = ent; // transfer ownership! target->nextthink = level.time + MEDIC_RESURRECT_DELAY; gi.linkentity(target); target->monsterinfo.stand(target); ent->num_monsters += target->monsterinfo.control_cost; safe_cprintf(ent, PRINT_HIGH, "Resurrected a %s. (%d/%d)\n", target->classname, ent->num_monsters, MAX_MONSTERS); } } else if ((!strcmp(target->classname, "bodyque") || !strcmp(target->classname, "player")) && (ent->num_monsters + 1 <= MAX_MONSTERS)) { int random=GetRandom(1, 3); vec3_t start; e = G_Spawn(); VectorCopy(target->s.origin, start); // kill the corpse T_Damage(target, target, target, vec3_origin, target->s.origin, vec3_origin, 10000, 0, DAMAGE_NO_PROTECTION, 0); //4.2 random soldier type with different weapons if (random == 1) { // blaster e->mtype = M_SOLDIER; e->s.skinnum = 0; } else if (random == 2) { // rocket e->mtype = M_SOLDIERLT; e->s.skinnum = 4; } else { // shotgun e->mtype = M_SOLDIERSS; e->s.skinnum = 2; } e->activator = ent; e->monsterinfo.level = skill_level; M_Initialize(ent, e); e->health = 0.2*e->max_health; e->monsterinfo.power_armor_power = 0.2*e->monsterinfo.max_armor; e->s.skinnum |= 1; // injured skin e->monsterinfo.stand(e); if (!G_IsValidLocation(target, start, e->mins, e->maxs)) { start[2] += 24; if (!G_IsValidLocation(target, start, e->mins, e->maxs)) { G_FreeEdict(e); return; } } VectorCopy(start, e->s.origin); gi.linkentity(e); e->nextthink = level.time + MEDIC_RESURRECT_DELAY; ent->num_monsters += e->monsterinfo.control_cost; safe_cprintf(ent, PRINT_HIGH, "Resurrected a soldier. (%d/%d)\n", ent->num_monsters, MAX_MONSTERS); } else if (!strcmp(target->classname, "spiker") && ent->num_spikers + 1 <= SPIKER_MAX_COUNT) { e = CreateSpiker(ent, skill_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_spikers--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = 0.33 * e->max_health; e->s.frame = 4; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); } else if (!strcmp(target->classname, "obstacle") && ent->num_obstacle + 1 <= OBSTACLE_MAX_COUNT) { e = CreateObstacle(ent, skill_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_obstacle--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = 0.33 * e->max_health; e->s.frame = 6; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); } else if (!strcmp(target->classname, "gasser") && ent->num_gasser + 1 <= GASSER_MAX_COUNT) { e = CreateGasser(ent, skill_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_gasser--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = 0.33 * e->max_health; e->s.frame = 0; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); } }
void p_medic_heal (edict_t *ent) { vec3_t forward, right, offset, start, end, org; trace_t tr; if (!p_medic_healframe(ent)) return; if (ent->s.frame == 218) gi.sound (ent, CHAN_WEAPON, gi.soundindex("medic/medatck2.wav"), 1, ATTN_NORM, 0); else if (ent->s.frame == 227) gi.sound (ent, CHAN_WEAPON, gi.soundindex("medic/medatck5.wav"), 1, ATTN_NORM, 0); // get muzzle location AngleVectors (ent->s.angles, forward, right, NULL); VectorCopy(p_medic_cable_offsets[ent->s.frame - 218], offset); G_ProjectSource(ent->s.origin, offset, forward, right, org); // get end position VectorCopy(ent->s.origin, start); start[2] += ent->viewheight; AngleVectors (ent->client->v_angle, forward, NULL, NULL); VectorMA(start, MEDIC_CABLE_RANGE, forward, end); tr = gi.trace (org, NULL, NULL, end, ent, MASK_SHOT); // bfg laser effect gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BFG_LASER); gi.WritePosition (org); gi.WritePosition (tr.endpos); gi.multicast (ent->s.origin, MULTICAST_PHS); if (G_EntExists(tr.ent)) { // try to heal them if they are alive if ((tr.ent->deadflag != DEAD_DEAD) && (tr.ent->health > 0)) { int frames = floattoint(600/(float)ent->myskills.abilities[MEDIC].current_level); if (!M_NeedRegen(tr.ent)) return; if (ent->s.frame == 220) gi.sound (ent, CHAN_WEAPON, gi.soundindex ("medic/medatck4.wav"), 1, ATTN_NORM, 0); // heal them M_Regenerate(tr.ent, frames, 0, 1.0, true, true, false, &tr.ent->monsterinfo.regen_delay2); // hold monsters in-place if (tr.ent->svflags & SVF_MONSTER) tr.ent->holdtime = level.time + 0.2; // remove all curses CurseRemove(tr.ent, 0); //Give them a short period of curse immunity tr.ent->holywaterProtection = level.time + 2.0; //2 seconds immunity } else { // try to reanimate/resurrect the corpse p_medic_reanimate(ent, tr.ent); } } }
void AddVote(edict_t *ent, int mode, int mapnum) { v_maplist_t *maplist = GetMapList(mode); if (!maplist) return; //check for valid choice if (mode && (maplist->nummaps > mapnum)) { char tempBuffer[1024]; //Add the vote voter = ent; numVotes = 1; ent->client->resp.HasVoted = true; strcpy(currentVote.ip, ent->client->pers.current_ip); strcpy(currentVote.name, ent->myskills.player_name); currentVote.mapindex = mapnum; currentVote.mode = mode; currentVote.used = true; voteTimeLeft = level.time + 90; Com_sprintf (tempBuffer, 1024, "%s started a vote for ", ent->myskills.player_name); switch(mode) { case MAPMODE_PVP: Com_sprintf (tempBuffer, 1024, "%sPlayer vs. Player (PvP) ", tempBuffer); break; case MAPMODE_PVM: Com_sprintf (tempBuffer, 1024, "%sPlayer vs. Monster (PvM) ", tempBuffer); break; case MAPMODE_DOM: Com_sprintf (tempBuffer, 1024, "%sDomination ", tempBuffer); break; case MAPMODE_CTF: Com_sprintf (tempBuffer, 1024, "%sCapture The Flag (CTF) ", tempBuffer); break; case MAPMODE_FFA: Com_sprintf (tempBuffer, 1024, "%sFree For All (FFA) ", tempBuffer); break; case MAPMODE_INV: Com_sprintf (tempBuffer, 1024, "%sInvasion ", tempBuffer); } Com_sprintf (tempBuffer, 1024, "%son %s\n", tempBuffer, maplist->maps[mapnum].name); gi.bprintf (PRINT_CHAT, "%s", tempBuffer); gi.bprintf (PRINT_HIGH, "Please place your vote by typing 'vote yes' or 'vote no' within the next %d seconds.\n", floattoint(voteTimeLeft-level.time)); } else gi.dprintf("Error in AddVote(): map number = %d, mode number = %d\n", mapnum, mode); }