mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-02-26 07:21:48 +00:00
Merge branch 'exp-polish' into 'master'
EXP polish See merge request kart-krew-dev/ring-racers-internal!2631
This commit is contained in:
commit
fc7b15d369
18 changed files with 292 additions and 6 deletions
|
|
@ -800,6 +800,7 @@ consvar_t cv_battleufotest = OnlineCheat("battleufotest", "Off").on_off().descri
|
|||
|
||||
#ifdef DEVELOP
|
||||
consvar_t cv_botcontrol = OnlineCheat("botcontrol", "On").on_off().description("Toggle bot AI movement");
|
||||
consvar_t cv_takeover = OnlineCheat("takeover", "Off").on_off().description("Human players use bot movement");
|
||||
#endif
|
||||
|
||||
extern CV_PossibleValue_t capsuletest_cons_t[];
|
||||
|
|
|
|||
|
|
@ -339,6 +339,11 @@ typedef enum
|
|||
// Tricks
|
||||
khud_trickcool,
|
||||
|
||||
// Exp
|
||||
khud_oldexp,
|
||||
khud_exp,
|
||||
khud_exptimer,
|
||||
|
||||
NUMKARTHUD
|
||||
} karthudtype_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -2686,6 +2686,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_EGOORB",
|
||||
|
||||
"S_AMPS",
|
||||
"S_EXP",
|
||||
|
||||
"S_WATERTRAIL1",
|
||||
"S_WATERTRAIL2",
|
||||
|
|
@ -4009,6 +4010,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_PULLUPHOOK",
|
||||
|
||||
"MT_AMPS",
|
||||
"MT_EXP",
|
||||
|
||||
"MT_FLYBOT767",
|
||||
|
||||
|
|
|
|||
31
src/info.c
31
src/info.c
|
|
@ -600,6 +600,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"AMPC",
|
||||
"AMPD",
|
||||
|
||||
"EXPC",
|
||||
|
||||
"SOR_",
|
||||
|
||||
"WTRL", // Water Trail
|
||||
|
|
@ -3246,6 +3248,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_EGOO, 0, 1, {NULL}, 0, 0, S_NULL}, // S_EGOORB
|
||||
|
||||
{SPR_AMPA, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 41, 1, S_NULL}, // S_AMPS
|
||||
{SPR_EXPC, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_EXP
|
||||
|
||||
// Water Trail
|
||||
{SPR_WTRL, FF_PAPERSPRITE , 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL1
|
||||
|
|
@ -22482,7 +22485,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_AMPS
|
||||
3444, // doomednum
|
||||
-1, // doomednum
|
||||
S_AMPS, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -22507,6 +22510,32 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP|MF_NOCLIPTHING, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_EXP
|
||||
-1, // doomednum
|
||||
S_EXP, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
1, // speed
|
||||
32*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // dispoffset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP|MF_NOCLIPTHING, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
{ // MT_FLYBOT767
|
||||
-1, // doomednum
|
||||
S_FLYBOT767, // spawnstate
|
||||
|
|
|
|||
|
|
@ -1141,6 +1141,8 @@ typedef enum sprite
|
|||
SPR_AMPC,
|
||||
SPR_AMPD,
|
||||
|
||||
SPR_EXPC,
|
||||
|
||||
SPR_SOR_,
|
||||
|
||||
SPR_WTRL, // Water Trail
|
||||
|
|
@ -3742,6 +3744,7 @@ typedef enum state
|
|||
S_EGOORB,
|
||||
|
||||
S_AMPS,
|
||||
S_EXP,
|
||||
|
||||
S_WATERTRAIL1,
|
||||
S_WATERTRAIL2,
|
||||
|
|
@ -5091,6 +5094,7 @@ typedef enum mobj_type
|
|||
MT_PULLUPHOOK,
|
||||
|
||||
MT_AMPS,
|
||||
MT_EXP,
|
||||
|
||||
MT_FLYBOT767,
|
||||
|
||||
|
|
|
|||
|
|
@ -432,6 +432,11 @@ boolean K_PlayerUsesBotMovement(const player_t *player)
|
|||
if (player->bot)
|
||||
return true;
|
||||
|
||||
#ifdef DEVELOP
|
||||
if (cv_takeover.value)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ extern "C" {
|
|||
|
||||
#ifdef DEVELOP
|
||||
extern consvar_t cv_botcontrol;
|
||||
extern consvar_t cv_takeover;
|
||||
#endif
|
||||
|
||||
// Maximum value of botvars.difficulty
|
||||
|
|
|
|||
|
|
@ -3921,7 +3921,7 @@ static boolean K_drawKartLaps(void)
|
|||
INT32 bump = 0;
|
||||
boolean drewsticker = false;
|
||||
|
||||
UINT16 displayEXP = stplyr->exp;
|
||||
UINT16 displayEXP = stplyr->karthud[khud_exp];
|
||||
|
||||
// Jesus Christ.
|
||||
// I do not understand the way this system of offsets is laid out at all,
|
||||
|
|
@ -3999,6 +3999,10 @@ static boolean K_drawKartLaps(void)
|
|||
}
|
||||
}
|
||||
|
||||
boolean dance = (stplyr->exp > (UINT32)stplyr->karthud[khud_exp]);
|
||||
INT32 danceflag = dance ? V_STRINGDANCE : 0;
|
||||
UINT16 dancecolor = dance ? SKINCOLOR_AQUAMARINE : 0;
|
||||
|
||||
// EXP
|
||||
if (displayEXP == UINT16_MAX)
|
||||
{
|
||||
|
|
@ -4048,9 +4052,15 @@ static boolean K_drawKartLaps(void)
|
|||
V_DrawMappedPatch(fr, fy, transflag|V_SLIDEIN|splitflags, kp_exp[1], colormap);
|
||||
|
||||
// EXP
|
||||
V_DrawScaledPatch(fr+11, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[displayEXP/100]);
|
||||
V_DrawScaledPatch(fr+15, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[displayEXP/10%10]);
|
||||
V_DrawScaledPatch(fr+19, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[displayEXP%10]);
|
||||
|
||||
using srb2::Draw;
|
||||
|
||||
Draw row = Draw(fr+11, fy).flags(V_HUDTRANS|V_SLIDEIN|splitflags|danceflag).font(Draw::Font::kPing).colorize(dancecolor);
|
||||
row.text("{:03}", displayEXP);
|
||||
|
||||
//V_DrawScaledPatch(fr+11, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[displayEXP/100]);
|
||||
//V_DrawScaledPatch(fr+15, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[displayEXP/10%10]);
|
||||
//V_DrawScaledPatch(fr+19, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[displayEXP%10]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4065,7 +4075,7 @@ static boolean K_drawKartLaps(void)
|
|||
V_DrawMappedPatch(LAPS_X+bump, LAPS_Y, transflag|V_SLIDEIN|splitflags, kp_exp[0], colormap);
|
||||
|
||||
using srb2::Draw;
|
||||
Draw row = Draw(LAPS_X+23+bump, LAPS_Y+3).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer);
|
||||
Draw row = Draw(LAPS_X+23+bump, LAPS_Y+3).flags(V_HUDTRANS|V_SLIDEIN|splitflags|danceflag).font(Draw::Font::kThinTimer).colorize(dancecolor);
|
||||
row.text("{:03}", displayEXP);
|
||||
}
|
||||
|
||||
|
|
|
|||
44
src/k_kart.c
44
src/k_kart.c
|
|
@ -4229,6 +4229,25 @@ void K_SpawnAmps(player_t *player, UINT8 amps, mobj_t *impact)
|
|||
}
|
||||
}
|
||||
|
||||
void K_SpawnEXP(player_t *player, UINT8 exp, mobj_t *impact)
|
||||
{
|
||||
if (exp == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < exp; i++)
|
||||
{
|
||||
mobj_t *pickup = P_SpawnMobj(impact->x, impact->y, impact->z, MT_EXP);
|
||||
pickup->momx = impact->momx;
|
||||
pickup->momy = impact->momy;
|
||||
pickup->momz = impact->momz;
|
||||
pickup->momx += P_RandomRange(PR_ITEM_DEBRIS, -20*mapobjectscale, 20*mapobjectscale);
|
||||
pickup->momy += P_RandomRange(PR_ITEM_DEBRIS, -20*mapobjectscale, 20*mapobjectscale);
|
||||
pickup->momz += P_RandomRange(PR_ITEM_DEBRIS, -20*mapobjectscale, 20*mapobjectscale);
|
||||
// pickup->color = player->skincolor;
|
||||
P_SetTarget(&pickup->target, player->mo);
|
||||
}
|
||||
}
|
||||
|
||||
void K_AwardPlayerAmps(player_t *player, UINT8 amps)
|
||||
{
|
||||
UINT16 getamped = player->amps + amps;
|
||||
|
|
@ -8879,6 +8898,31 @@ void K_KartPlayerHUDUpdate(player_t *player)
|
|||
if (player->positiondelay)
|
||||
player->positiondelay--;
|
||||
|
||||
if (player->exp != (UINT32)player->karthud[khud_oldexp])
|
||||
{
|
||||
if (player->exp <= (UINT32)player->karthud[khud_oldexp])
|
||||
{
|
||||
player->karthud[khud_oldexp] = 0;
|
||||
player->karthud[khud_exp] = 0;
|
||||
player->karthud[khud_exptimer] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 delta = player->exp - player->karthud[khud_exp];
|
||||
INT32 speed = max(1, 10-delta);
|
||||
|
||||
player->karthud[khud_exptimer]++;
|
||||
|
||||
if (player->karthud[khud_exptimer] >= speed)
|
||||
{
|
||||
player->karthud[khud_exp]++;
|
||||
player->karthud[khud_exptimer] = 0;
|
||||
if (player->exp == (UINT32)player->karthud[khud_exp])
|
||||
player->karthud[khud_oldexp] = player->exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(player->pflags & PF_FAULT || player->pflags & PF_VOID))
|
||||
player->karthud[khud_fault] = 0;
|
||||
else if (player->karthud[khud_fault] > 0 && player->karthud[khud_fault] <= 2*TICRATE)
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ angle_t K_MomentumAngleReal(const mobj_t *mo);
|
|||
#define K_MomentumAngle(mo) K_MomentumAngleEx(mo, 6 * mo->scale)
|
||||
boolean K_PvPAmpReward(UINT32 award, player_t *attacker, player_t *defender);
|
||||
void K_SpawnAmps(player_t *player, UINT8 amps, mobj_t *impact);
|
||||
void K_SpawnEXP(player_t *player, UINT8 exp, mobj_t *impact);
|
||||
void K_AwardPlayerAmps(player_t *player, UINT8 amps);
|
||||
void K_CheckpointCrossAward(player_t *player);
|
||||
void K_AwardPlayerRings(player_t *player, UINT16 rings, boolean overload);
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ void Obj_AmpBurstThink(mobj_t *amp);
|
|||
|
||||
void Obj_AmpsThink(mobj_t *amps);
|
||||
|
||||
void Obj_ExpThink(mobj_t *exp);
|
||||
|
||||
void Obj_ChargeAuraThink(mobj_t *aura);
|
||||
void Obj_ChargeFallThink(mobj_t *charge);
|
||||
void Obj_ChargeReleaseThink(mobj_t *release);
|
||||
|
|
|
|||
15
src/k_race.c
15
src/k_race.c
|
|
@ -468,3 +468,18 @@ UINT8 K_RaceLapCount(INT16 mapNum)
|
|||
|
||||
return cv_numlaps.value;
|
||||
}
|
||||
|
||||
void K_SpawnFinishEXP(player_t *player, UINT16 exp)
|
||||
{
|
||||
if (finishBeamLine != NULL)
|
||||
{
|
||||
mobj_t *p1 = P_SpawnMobj(finishBeamLine->v1->x, finishBeamLine->v1->y, player->mo->z, MT_THOK);
|
||||
mobj_t *p2 = P_SpawnMobj(finishBeamLine->v2->x, finishBeamLine->v2->y, player->mo->z, MT_THOK);
|
||||
K_SpawnEXP(player, exp, p1);
|
||||
K_SpawnEXP(player, exp, p2);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_SpawnEXP(player, exp*2, player->mo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ void K_RunFinishLineBeam(void);
|
|||
|
||||
UINT8 K_RaceLapCount(INT16 mapNum);
|
||||
|
||||
void K_SpawnFinishEXP(player_t *player, UINT16 exp);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
lightning-shield.cpp
|
||||
flame-shield.cpp
|
||||
stone-shoe.cpp
|
||||
exp.c
|
||||
)
|
||||
|
||||
add_subdirectory(versus)
|
||||
|
|
|
|||
|
|
@ -688,8 +688,17 @@ void Obj_CrossCheckpoints(player_t* player, fixed_t old_x, fixed_t old_y)
|
|||
|
||||
player->checkpointId = chk->id();
|
||||
|
||||
UINT16 oldexp = player->exp;
|
||||
|
||||
K_CheckpointCrossAward(player);
|
||||
|
||||
if (player->exp > oldexp)
|
||||
{
|
||||
UINT16 expdiff = (player->exp - oldexp);
|
||||
K_SpawnEXP(player, expdiff, chk);
|
||||
K_SpawnEXP(player, expdiff, chk->other());
|
||||
}
|
||||
|
||||
K_UpdatePowerLevels(player, player->laps, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
143
src/objects/exp.c
Normal file
143
src/objects/exp.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by AJ "Tyron" Martinez.
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file amps.c
|
||||
/// \brief EXP VFX code.
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../info.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../p_local.h"
|
||||
#include "../k_kart.h"
|
||||
#include "../k_powerup.h"
|
||||
#include "../m_random.h"
|
||||
#include "../r_main.h"
|
||||
#include "../m_easing.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../sounds.h"
|
||||
|
||||
#define EXP_ARCTIME (8)
|
||||
#define EXP_ORBIT (100)
|
||||
|
||||
static void ghostme(mobj_t *exp, player_t *player)
|
||||
{
|
||||
if (exp->cusval%2)
|
||||
return;
|
||||
|
||||
mobj_t *ghost = P_SpawnGhostMobj(exp);
|
||||
ghost->colorized = true;
|
||||
ghost->color = player->skincolor;
|
||||
ghost->renderflags |= RF_ADD;
|
||||
ghost->fuse = 2;
|
||||
}
|
||||
|
||||
void Obj_ExpThink (mobj_t *exp)
|
||||
{
|
||||
if (P_MobjWasRemoved(exp->target)
|
||||
|| exp->target->health == 0
|
||||
|| exp->target->destscale <= 1 // sealed star fall out
|
||||
|| !exp->target->player)
|
||||
{
|
||||
P_RemoveMobj(exp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo = exp->target;
|
||||
player_t *player = mo->player;
|
||||
|
||||
fixed_t dist, fakez;
|
||||
angle_t hang, vang;
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(exp->x - mo->x, exp->y - mo->y), exp->z - mo->z);
|
||||
|
||||
exp->renderflags |= RF_DONTDRAW;
|
||||
exp->renderflags &= ~K_GetPlayerDontDrawFlag(player);
|
||||
|
||||
// K_MatchGenericExtraFlags(exp, mo);
|
||||
|
||||
exp->cusval++;
|
||||
|
||||
// bullshit copypaste orbit behavior
|
||||
if (exp->threshold)
|
||||
{
|
||||
fixed_t orbit = (4*mo->scale) * (16 - exp->extravalue1);
|
||||
|
||||
P_SetScale(exp, (exp->destscale = mapobjectscale - ((mapobjectscale/28) * exp->extravalue1)));
|
||||
exp->z = exp->target->z;
|
||||
P_MoveOrigin(exp,
|
||||
mo->x + FixedMul(orbit, FINECOSINE(exp->angle >> ANGLETOFINESHIFT)),
|
||||
mo->y + FixedMul(orbit, FINESINE(exp->angle >> ANGLETOFINESHIFT)),
|
||||
exp->z + mo->scale * 24 * P_MobjFlip(exp));
|
||||
|
||||
exp->momx = 0;
|
||||
exp->momy = 0;
|
||||
exp->momz = 0;
|
||||
|
||||
ghostme(exp, player);
|
||||
|
||||
exp->angle += ANG30;
|
||||
exp->extravalue1++;
|
||||
|
||||
if (exp->extravalue1 >= 16)
|
||||
P_RemoveMobj(exp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exp->angle += ANGLE_45/2;
|
||||
|
||||
UINT8 damper = 3;
|
||||
|
||||
fixed_t vert = dist/3;
|
||||
fixed_t speed = 60*exp->scale;
|
||||
|
||||
if (exp->extravalue2) // Mode: going down, aim at the player and speed up / dampen stray movement
|
||||
{
|
||||
if (exp->extravalue1)
|
||||
exp->extravalue1--;
|
||||
|
||||
exp->extravalue2++;
|
||||
|
||||
speed += exp->extravalue2 * exp->scale/2;
|
||||
|
||||
fakez = mo->z + (vert * exp->extravalue1 / EXP_ARCTIME);
|
||||
damper = 1;
|
||||
}
|
||||
else // Mode: going up, aim above the player
|
||||
{
|
||||
exp->extravalue1++;
|
||||
if (exp->extravalue1 >= EXP_ARCTIME)
|
||||
exp->extravalue2 = 1;
|
||||
|
||||
fakez = mo->z + vert;
|
||||
}
|
||||
|
||||
if (mo->flags & MFE_VERTICALFLIP)
|
||||
fakez -= mo->height/2;
|
||||
else
|
||||
fakez += mo->height/2;
|
||||
|
||||
hang = R_PointToAngle2(exp->x, exp->y, mo->x, mo->y);
|
||||
vang = R_PointToAngle2(exp->z, 0, fakez, dist);
|
||||
|
||||
exp->momx -= exp->momx>>(damper), exp->momy -= exp->momy>>(damper), exp->momz -= exp->momz>>(damper);
|
||||
exp->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), speed));
|
||||
exp->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), speed));
|
||||
exp->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), speed);
|
||||
|
||||
ghostme(exp, player);
|
||||
|
||||
if (dist < (EXP_ORBIT * exp->scale) && exp->extravalue2)
|
||||
{
|
||||
exp->threshold = TICRATE;
|
||||
exp->extravalue1 = 0;
|
||||
exp->extravalue2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8908,6 +8908,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
Obj_AmpsThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_EXP:
|
||||
{
|
||||
Obj_ExpThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_BLOCKRING:
|
||||
{
|
||||
Obj_BlockRingThink(mobj);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include "music.h"
|
||||
#include "k_battle.h" // battleprisons
|
||||
#include "k_endcam.h" // K_EndCameraIsFreezing()
|
||||
#include "k_race.h" // K_SpawnFinishEXP
|
||||
|
||||
// Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog
|
||||
#include <errno.h>
|
||||
|
|
@ -2153,8 +2154,14 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
// Update power levels for this lap.
|
||||
K_UpdatePowerLevels(player, player->laps, false);
|
||||
|
||||
UINT16 oldexp = player->exp;
|
||||
K_CheckpointCrossAward(player);
|
||||
|
||||
if (player->exp > oldexp)
|
||||
{
|
||||
K_SpawnFinishEXP(player, player->exp - oldexp);
|
||||
}
|
||||
|
||||
if (player->position == 1 && !(gametyperules & GTR_CHECKPOINTS))
|
||||
{
|
||||
Obj_DeactivateCheckpoints();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue