/** * @brief Drop weapon. */ void G_DropWeapon(gentity_t *ent, weapon_t weapon) { vec3_t angles, velocity, org, offset, mins, maxs; gclient_t *client = ent->client; gentity_t *ent2; gitem_t *item; trace_t tr; if (!IS_VALID_WEAPON(weapon)) { return; } item = BG_FindItemForWeapon(weapon); VectorCopy(client->ps.viewangles, angles); // clamp pitch if (angles[PITCH] < -30) { angles[PITCH] = -30; } else if (angles[PITCH] > 30) { angles[PITCH] = 30; } AngleVectors(angles, velocity, NULL, NULL); VectorScale(velocity, 64, offset); offset[2] += client->ps.viewheight / 2.f; VectorScale(velocity, 75, velocity); velocity[2] += 50 + random() * 35; VectorAdd(client->ps.origin, offset, org); VectorSet(mins, -ITEM_RADIUS, -ITEM_RADIUS, 0); VectorSet(maxs, ITEM_RADIUS, ITEM_RADIUS, 2 * ITEM_RADIUS); trap_Trace(&tr, client->ps.origin, mins, maxs, org, ent->s.number, MASK_SOLID); VectorCopy(tr.endpos, org); ent2 = LaunchItem(item, org, velocity, client->ps.clientNum); COM_BitClear(client->ps.weapons, weapon); switch (weapon) { case WP_KAR98: COM_BitClear(client->ps.weapons, WP_GPG40); break; case WP_CARBINE: COM_BitClear(client->ps.weapons, WP_M7); break; case WP_FG42: COM_BitClear(client->ps.weapons, WP_FG42SCOPE); break; case WP_K43: COM_BitClear(client->ps.weapons, WP_K43_SCOPE); break; case WP_GARAND: COM_BitClear(client->ps.weapons, WP_GARAND_SCOPE); break; case WP_MORTAR: COM_BitClear(client->ps.weapons, WP_MORTAR_SET); break; case WP_MORTAR2: COM_BitClear(client->ps.weapons, WP_MORTAR2_SET); break; case WP_MOBILE_MG42: COM_BitClear(client->ps.weapons, WP_MOBILE_MG42_SET); break; case WP_MOBILE_BROWNING: COM_BitClear(client->ps.weapons, WP_MOBILE_BROWNING_SET); break; default: break; } // Clear out empty weapon, change to next best weapon G_AddEvent(ent, EV_WEAPONSWITCHED, 0); if (weapon == client->ps.weapon) { client->ps.weapon = 0; } if (IS_MORTAR_WEAPON_SET(weapon)) { ent2->count = client->ps.ammo[BG_FindAmmoForWeapon(weapon)] + client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; } else { ent2->count = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; } if (weapon == WP_KAR98 || weapon == WP_CARBINE) { ent2->delay = client->ps.ammo[BG_FindAmmoForWeapon(weaponTable[weapon].weapAlts)]; } else { ent2->delay = 0; } // ent2->item->quantity = client->ps.ammoclip[BG_FindClipForWeapon(weapon)]; // um, modifying an item is not a good idea client->ps.ammoclip[BG_FindClipForWeapon(weapon)] = 0; #ifdef FEATURE_OMNIBOT Bot_Event_RemoveWeapon(client->ps.clientNum, Bot_WeaponGameToBot(weapon)); #endif }
/** * @brief Pick a weapon up. */ int Pickup_Weapon(gentity_t *ent, gentity_t *other) { int quantity; qboolean alreadyHave = qfalse; // magic ammo for any two-handed weapon if (ent->item->giTag == WP_AMMO) { AddMagicAmmo(other, ent->count); if (ent->parent && ent->parent->client) { other->client->pers.lastammo_client = ent->parent->s.clientNum; } // if LT isn't giving ammo to self or another LT or the enemy, give him some props if (other->client->ps.stats[STAT_PLAYER_CLASS] != PC_FIELDOPS) { if (ent->parent && ent->parent->client && other->client->sess.sessionTeam == ent->parent->client->sess.sessionTeam) { if (!(ent->parent->client->PCSpecialPickedUpCount % LT_SPECIAL_PICKUP_MOD)) { AddScore(ent->parent, WOLF_AMMO_UP); if (ent->parent && ent->parent->client) { G_LogPrintf("Ammo_Pack: %d %d\n", (int)(ent->parent - g_entities), (int)(other - g_entities)); } } ent->parent->client->PCSpecialPickedUpCount++; G_AddSkillPoints(ent->parent, SK_SIGNALS, 1.f); G_DebugAddSkillPoints(ent->parent, SK_SIGNALS, 1.f, "ammo pack picked up"); #ifdef FEATURE_OMNIBOT //omni-bot event if (ent->parent) { Bot_Event_RecievedAmmo(other - g_entities, ent->parent); } #endif // extracted code originally here into AddMagicAmmo // add 1 clip of magic ammo for any two-handed weapon } return RESPAWN_NEVER; } } quantity = ent->count; // check if player already had the weapon alreadyHave = COM_BitCheck(other->client->ps.weapons, ent->item->giTag); // prevents drop/pickup weapon "quick reload" exploit if (alreadyHave) { Add_Ammo(other, ent->item->giTag, quantity, qfalse); // secondary weapon ammo if (ent->delay) { Add_Ammo(other, weaponTable[ent->item->giTag].weapAlts, ent->delay, qfalse); } } else { if (level.time - other->client->dropWeaponTime < 1000) { return 0; } // don't pick up when MG or mortar is set if (IS_MORTAR_WEAPON_SET(other->client->ps.weapon) || IS_MG_WEAPON_SET(other->client->ps.weapon)) { return 0; } // see if we can pick it up if (G_CanPickupWeapon(ent->item->giTag, other)) { weapon_t primaryWeapon; if (other->client->sess.playerType == PC_SOLDIER && other->client->sess.skill[SK_HEAVY_WEAPONS] >= 4) { primaryWeapon = G_GetPrimaryWeaponForClientSoldier(ent->item->giTag, other->client); } else { primaryWeapon = G_GetPrimaryWeaponForClient(other->client); } // added parens around ambiguous && if (primaryWeapon) { // drop our primary weapon G_DropWeapon(other, primaryWeapon); // now pickup the other one other->client->dropWeaponTime = level.time; // add the weapon COM_BitSet(other->client->ps.weapons, ent->item->giTag); // fixup mauser/sniper issues switch (ent->item->giTag) { case WP_FG42: COM_BitSet(other->client->ps.weapons, WP_FG42SCOPE); break; case WP_GARAND: COM_BitSet(other->client->ps.weapons, WP_GARAND_SCOPE); break; case WP_K43: COM_BitSet(other->client->ps.weapons, WP_K43_SCOPE); break; case WP_MORTAR: COM_BitSet(other->client->ps.weapons, WP_MORTAR_SET); break; case WP_MORTAR2: COM_BitSet(other->client->ps.weapons, WP_MORTAR2_SET); break; case WP_MOBILE_MG42: COM_BitSet(other->client->ps.weapons, WP_MOBILE_MG42_SET); break; case WP_MOBILE_BROWNING: COM_BitSet(other->client->ps.weapons, WP_MOBILE_BROWNING_SET); break; case WP_CARBINE: COM_BitSet(other->client->ps.weapons, WP_M7); break; case WP_KAR98: COM_BitSet(other->client->ps.weapons, WP_GPG40); break; default: break; } other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = 0; other->client->ps.ammo[BG_FindAmmoForWeapon(ent->item->giTag)] = 0; if (ent->item->giTag == WP_MORTAR || ent->item->giTag == WP_MORTAR2) { other->client->ps.ammo[BG_FindClipForWeapon(ent->item->giTag)] = quantity; // secondary weapon ammo if (ent->delay) { Add_Ammo(other, weaponTable[ent->item->giTag].weapAlts, ent->delay, qfalse); } } else { other->client->ps.ammoclip[BG_FindClipForWeapon(ent->item->giTag)] = quantity; // secondary weapon ammo if (ent->delay) { other->client->ps.ammo[weaponTable[ent->item->giTag].weapAlts] = ent->delay; } } } } else { return 0; } } #ifdef FEATURE_OMNIBOT Bot_Event_AddWeapon(other->client->ps.clientNum, Bot_WeaponGameToBot(ent->item->giTag)); #endif return RESPAWN_NEVER; }
void CG_DrawMortarMarker(int px, int py, int pw, int ph, qboolean draw, mapScissor_t *scissor, int expand) { if (IS_MORTAR_WEAPON_SET(cg.lastFiredWeapon) && cg.mortarImpactTime >= 0) { if (cg.snap->ps.weapon != WP_MORTAR_SET && cg.snap->ps.weapon != WP_MORTAR2_SET) { cg.mortarImpactTime = 0; } else { vec4_t colour = { 1.f, 1.f, 1.f, 1.f }; vec3_t point; if (scissor) { point[0] = ((cg.mortarImpactPos[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor; point[1] = ((cg.mortarImpactPos[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor; } else { point[0] = px + (((cg.mortarImpactPos[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw); point[1] = py + (((cg.mortarImpactPos[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph); } // don't return if the marker is culled, just don't draw it if (!(scissor && CG_ScissorPointIsCulled(point, scissor))) { if (scissor) { point[0] += px - scissor->tl[0]; point[1] += py - scissor->tl[1]; } if (cg.mortarImpactOutOfMap) { if (!scissor) { // near the edge of the map, fit into it if (point[0] + 8.f > (px + pw)) { point[0] -= 8.f; } else if (point[0] - 8.f < px) { point[0] += 8.f; } if (point[1] + 8.f > (py + ph)) { point[1] -= 8.f; } else if (point[1] - 8.f < py) { point[1] += 8.f; } } colour[3] = .5f; } trap_R_SetColor(colour); CG_DrawRotatedPic(point[0] - 8.f, point[1] - 8.f, 16, 16, cgs.media.ccMortarHit, .5f - (cg.mortarFireAngles[YAW] /*- 180.f */ + 45.f) / 360.f); trap_R_SetColor(NULL); } } } if (COM_BitCheck(cg.snap->ps.weapons, WP_MORTAR_SET) || COM_BitCheck(cg.snap->ps.weapons, WP_MORTAR2_SET)) { vec4_t colour = { 1.f, 1.f, 1.f, 1.f }; vec3_t point; int i, fadeTime; for (i = 0; i < cgs.maxclients; i++) { fadeTime = cg.time - (cg.artilleryRequestTime[i] + 25000); if (fadeTime < 5000) { if (fadeTime > 0) { colour[3] = 1.f - (fadeTime / 5000.f); } if (scissor) { point[0] = ((cg.artilleryRequestPos[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor; point[1] = ((cg.artilleryRequestPos[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor; } else { point[0] = px + (((cg.artilleryRequestPos[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw); point[1] = py + (((cg.artilleryRequestPos[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph); } // don't return if the marker is culled, just skip it (so we draw the rest, if any) if (scissor && CG_ScissorPointIsCulled(point, scissor)) { continue; } if (scissor) { point[0] += px - scissor->tl[0]; point[1] += py - scissor->tl[1]; } trap_R_SetColor(colour); CG_DrawPic(point[0] - 8.f, point[1] - 8.f, 16, 16, cgs.media.ccMortarTarget); trap_R_SetColor(NULL); } } } }