/** * Exponentially decreases momentum. */ void G_DecreaseMomentum() { int team; float amount; static float decreaseFactor = 1.0f, lastMomentumHalfLife = 0.0f; static int nextCalculation = 0; if ( level.time < nextCalculation ) { return; } if ( g_momentumHalfLife.value <= 0.0f ) { return; } // only calculate decreaseFactor if the server configuration changed if ( lastMomentumHalfLife != g_momentumHalfLife.value ) { // ln(2) ~= 0.6931472 decreaseFactor = exp( ( -0.6931472f / ( ( 60000.0f / DECREASE_MOMENTUM_PERIOD ) * g_momentumHalfLife.value ) ) ); lastMomentumHalfLife = g_momentumHalfLife.value; } // decrease momentum for ( team = TEAM_NONE + 1; team < NUM_TEAMS; team++ ) { amount = level.team[ team ].momentum * ( decreaseFactor - 1.0f ); level.team[ team ].momentum += amount; // notify legacy stage sensors NotifyLegacyStageSensors( (team_t) team, amount ); } MomentumChanged(); nextCalculation = level.time + DECREASE_MOMENTUM_PERIOD; }
/** * Awards momentum to a team. * * Will notify the client hwo earned it if given, otherwise the whole team, with *an event. */ static float AddMomentum(momentum_t type, team_t team, float amount, gentity_t* source, bool skipChangeHook) { gentity_t* event = nullptr; gclient_t* client; char* clientName; if (team <= TEAM_NONE || team >= NUM_TEAMS) { return 0.0f; } // apply modifier amount *= MomentumMod(type); // limit a team's total if (level.team[team].momentum + amount > MOMENTUM_MAX) { amount = MOMENTUM_MAX - level.team[team].momentum; } if (amount != 0.0f) { // add momentum to team level.team[team].momentum += amount; // run change hook if requested if (!skipChangeHook) { MomentumChanged(); } // notify source if (source) { client = source->client; if (client && client->pers.team == team) { event = G_NewTempEntity(client->ps.origin, EV_MOMENTUM); event->r.svFlags = SVF_SINGLECLIENT; event->r.singleClient = client->ps.clientNum; } } else { event = G_NewTempEntity(vec3_origin, EV_MOMENTUM); event->r.svFlags = (SVF_BROADCAST | SVF_CLIENTMASK); G_TeamToClientmask(team, &(event->r.loMask), &(event->r.hiMask)); } if (event) { // TODO: Use more bits for momentum value event->s.eventParm = 0; event->s.otherEntityNum = 0; event->s.otherEntityNum2 = (int) (fabs(amount) * 10.0f + 0.5f); event->s.groundEntityNum = amount < 0.0f ? true : false; } // notify legacy stage sensors NotifyLegacyStageSensors(team, amount); } if (g_debugMomentum.integer > 0) { if (source && source->client) { clientName = source->client->pers.netname; } else { clientName = "no source"; } Com_Printf("Momentum: %.2f to %s (%s by %s for %s)\n", amount, BG_TeamNamePlural(team), amount < 0.0f ? "lost" : "earned", clientName, MomentumTypeToReason(type)); } return amount; }