mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'spraycans-2' into 'master'
Tutorial Spray Cans Closes #669 See merge request KartKrew/Kart!1498
This commit is contained in:
commit
9ba5a93407
7 changed files with 160 additions and 12 deletions
|
|
@ -40,6 +40,7 @@
|
||||||
#include "../m_cond.h"
|
#include "../m_cond.h"
|
||||||
#include "../r_skins.h"
|
#include "../r_skins.h"
|
||||||
#include "../k_battle.h"
|
#include "../k_battle.h"
|
||||||
|
#include "../k_grandprix.h"
|
||||||
#include "../k_podium.h"
|
#include "../k_podium.h"
|
||||||
#include "../k_bot.h"
|
#include "../k_bot.h"
|
||||||
#include "../z_zone.h"
|
#include "../z_zone.h"
|
||||||
|
|
@ -680,6 +681,12 @@ bool CallFunc_DialogueWaitDismiss(ACSVM::Thread *thread, const ACSVM::Word *argV
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
|
// TODO when we move away from g_dialogue
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
g_dialogue.SetDismissable(true);
|
g_dialogue.SetDismissable(true);
|
||||||
|
|
||||||
thread->state = {
|
thread->state = {
|
||||||
|
|
@ -702,6 +709,12 @@ bool CallFunc_DialogueWaitText(ACSVM::Thread *thread, const ACSVM::Word *argV, A
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
|
// TODO when we move away from g_dialogue
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
g_dialogue.SetDismissable(false);
|
g_dialogue.SetDismissable(false);
|
||||||
|
|
||||||
thread->state = {
|
thread->state = {
|
||||||
|
|
@ -1699,6 +1712,57 @@ bool CallFunc_TimeAttack(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
bool CallFunc_GrandPrix(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
|
Returns if a Grand Prix is active.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
bool CallFunc_GrandPrix(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
{
|
||||||
|
(void)argV;
|
||||||
|
(void)argC;
|
||||||
|
|
||||||
|
thread->dataStk.push(grandprixinfo.gp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
bool CallFunc_GetGrabbedSprayCan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
|
Returns the level's associated Spray Can, if grabbed.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
bool CallFunc_GetGrabbedSprayCan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
{
|
||||||
|
Environment *env = &ACSEnv;
|
||||||
|
|
||||||
|
(void)argV;
|
||||||
|
(void)argC;
|
||||||
|
|
||||||
|
if (netgame == false // cans are per-player and completely unsyncable
|
||||||
|
&& gamemap-1 < basenummapheaders)
|
||||||
|
{
|
||||||
|
// See also P_SprayCanInit
|
||||||
|
UINT16 can_id = mapheaderinfo[gamemap-1]->cache_spraycan;
|
||||||
|
|
||||||
|
if (can_id < gamedata->numspraycans)
|
||||||
|
{
|
||||||
|
UINT16 col = gamedata->spraycans[can_id].col;
|
||||||
|
|
||||||
|
thread->dataStk.push(~env->getString( skincolors[col].name )->idx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamedata->gotspraycans >= gamedata->numspraycans)
|
||||||
|
{
|
||||||
|
thread->dataStk.push(~env->getString( "_Completed" )->idx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->dataStk.push(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool CallFunc_PodiumPosition(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
bool CallFunc_PodiumPosition(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
|
|
@ -1925,6 +1989,12 @@ bool CallFunc_DialogueSetSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV,
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
|
// TODO when we move away from g_dialogue
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
map = thread->scopeMap;
|
map = thread->scopeMap;
|
||||||
|
|
||||||
skinStr = map->getString(argV[0]);
|
skinStr = map->getString(argV[0]);
|
||||||
|
|
@ -1963,6 +2033,12 @@ bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
|
// TODO when we move away from g_dialogue
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
map = thread->scopeMap;
|
map = thread->scopeMap;
|
||||||
|
|
||||||
nametagStr = map->getString(argV[0]);
|
nametagStr = map->getString(argV[0]);
|
||||||
|
|
@ -2044,6 +2120,12 @@ bool CallFunc_DialogueNewText(ACSVM::Thread *thread, const ACSVM::Word *argV, AC
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
|
// TODO when we move away from g_dialogue
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
map = thread->scopeMap;
|
map = thread->scopeMap;
|
||||||
|
|
||||||
textStr = map->getString(argV[0]);
|
textStr = map->getString(argV[0]);
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ bool CallFunc_LowestLap(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::W
|
||||||
bool CallFunc_EncoreMode(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_EncoreMode(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
bool CallFunc_BreakTheCapsules(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_BreakTheCapsules(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
bool CallFunc_TimeAttack(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_TimeAttack(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_GrandPrix(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_GetGrabbedSprayCan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
||||||
bool CallFunc_PodiumPosition(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_PodiumPosition(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
bool CallFunc_PodiumFinish(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_PodiumFinish(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,8 @@ Environment::Environment()
|
||||||
addFuncDataACS0( 310, addCallFunc(CallFunc_BreakTheCapsules));
|
addFuncDataACS0( 310, addCallFunc(CallFunc_BreakTheCapsules));
|
||||||
addFuncDataACS0( 311, addCallFunc(CallFunc_TimeAttack));
|
addFuncDataACS0( 311, addCallFunc(CallFunc_TimeAttack));
|
||||||
addFuncDataACS0( 312, addCallFunc(CallFunc_ThingCount));
|
addFuncDataACS0( 312, addCallFunc(CallFunc_ThingCount));
|
||||||
|
addFuncDataACS0( 313, addCallFunc(CallFunc_GrandPrix));
|
||||||
|
addFuncDataACS0( 314, addCallFunc(CallFunc_GetGrabbedSprayCan));
|
||||||
|
|
||||||
addFuncDataACS0( 500, addCallFunc(CallFunc_CameraWait));
|
addFuncDataACS0( 500, addCallFunc(CallFunc_CameraWait));
|
||||||
addFuncDataACS0( 501, addCallFunc(CallFunc_PodiumPosition));
|
addFuncDataACS0( 501, addCallFunc(CallFunc_PodiumPosition));
|
||||||
|
|
@ -299,6 +301,12 @@ bool Environment::checkTag(ACSVM::Word type, ACSVM::Word tag)
|
||||||
|
|
||||||
case ACS_TAGTYPE_DIALOGUE:
|
case ACS_TAGTYPE_DIALOGUE:
|
||||||
{
|
{
|
||||||
|
// TODO when we move away from g_dialogue
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (tag == 0) // cheeky reuse
|
if (tag == 0) // cheeky reuse
|
||||||
{
|
{
|
||||||
// wait for dismissal
|
// wait for dismissal
|
||||||
|
|
|
||||||
|
|
@ -157,9 +157,20 @@ void Dialogue::WriteText(void)
|
||||||
|
|
||||||
while (textTimer <= 0 && !textDest.empty())
|
while (textTimer <= 0 && !textDest.empty())
|
||||||
{
|
{
|
||||||
char c = textDest.back();
|
char c = textDest.back(), nextc = '\n';
|
||||||
text.push_back(c);
|
text.push_back(c);
|
||||||
|
|
||||||
|
textDest.pop_back();
|
||||||
|
|
||||||
|
if (c & 0x80)
|
||||||
|
{
|
||||||
|
// Color code support
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textDest.empty())
|
||||||
|
nextc = textDest.back();
|
||||||
|
|
||||||
if (voicePlayed == false
|
if (voicePlayed == false
|
||||||
&& std::isprint(c)
|
&& std::isprint(c)
|
||||||
&& c != ' ')
|
&& c != ' ')
|
||||||
|
|
@ -174,7 +185,8 @@ void Dialogue::WriteText(void)
|
||||||
voicePlayed = true;
|
voicePlayed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '.' || c == ',' || c == ';' || c == '!' || c == '?')
|
if (std::ispunct(c)
|
||||||
|
&& std::isspace(nextc))
|
||||||
{
|
{
|
||||||
// slow down for punctuation
|
// slow down for punctuation
|
||||||
textTimer += kTextPunctPause;
|
textTimer += kTextPunctPause;
|
||||||
|
|
@ -183,8 +195,6 @@ void Dialogue::WriteText(void)
|
||||||
{
|
{
|
||||||
textTimer += FRACUNIT;
|
textTimer += FRACUNIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
textDest.pop_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textDone = (textTimer <= 0 && textDest.empty());
|
textDone = (textTimer <= 0 && textDest.empty());
|
||||||
|
|
|
||||||
|
|
@ -692,6 +692,25 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
{
|
{
|
||||||
// Unassigned, get the next grabbable colour
|
// Unassigned, get the next grabbable colour
|
||||||
can_id = gamedata->gotspraycans;
|
can_id = gamedata->gotspraycans;
|
||||||
|
|
||||||
|
// Multiple cans in one map?
|
||||||
|
if (special->threshold != 0)
|
||||||
|
{
|
||||||
|
UINT16 ref_id = can_id + (special->threshold & UINT8_MAX);
|
||||||
|
if (ref_id >= gamedata->numspraycans)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Swap this specific can to the head of the list.
|
||||||
|
UINT16 swapcol = gamedata->spraycans[ref_id].col;
|
||||||
|
|
||||||
|
gamedata->spraycans[ref_id].col =
|
||||||
|
gamedata->spraycans[can_id].col;
|
||||||
|
skincolors[gamedata->spraycans[ref_id].col].cache_spraycan = ref_id;
|
||||||
|
|
||||||
|
gamedata->spraycans[can_id].col = swapcol;
|
||||||
|
skincolors[swapcol].cache_spraycan = can_id;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_id >= gamedata->numspraycans)
|
if (can_id >= gamedata->numspraycans)
|
||||||
|
|
@ -712,8 +731,30 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
gamedata->deferredsave = true;
|
gamedata->deferredsave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't delete the object, just fade it.
|
{
|
||||||
P_SprayCanInit(special);
|
mobj_t *canmo = NULL;
|
||||||
|
mobj_t *next = NULL;
|
||||||
|
|
||||||
|
for (canmo = trackercap; canmo; canmo = next)
|
||||||
|
{
|
||||||
|
next = canmo->itnext;
|
||||||
|
|
||||||
|
if (canmo->type != MT_SPRAYCAN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Don't delete the object(s), just fade it.
|
||||||
|
if (netgame || canmo == special)
|
||||||
|
{
|
||||||
|
P_SprayCanInit(canmo);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get ready to get rid of these
|
||||||
|
canmo->renderflags |= (tr_trans50 << RF_TRANSSHIFT);
|
||||||
|
canmo->destscale = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
14
src/p_mobj.c
14
src/p_mobj.c
|
|
@ -12463,8 +12463,14 @@ void P_SprayCanInit(mobj_t* mobj)
|
||||||
// Prevent footguns - these won't persist when custom levels are unloaded
|
// Prevent footguns - these won't persist when custom levels are unloaded
|
||||||
else if (gamemap-1 < basenummapheaders)
|
else if (gamemap-1 < basenummapheaders)
|
||||||
{
|
{
|
||||||
// Unassigned, get the next grabbable colour
|
// Unassigned, get the next grabbable colour (offset by threshold)
|
||||||
can_id = gamedata->gotspraycans;
|
can_id = gamedata->gotspraycans;
|
||||||
|
|
||||||
|
// It's ok if this goes over gamedata->numspraycans, as they're
|
||||||
|
// capped below in this func... but NEVER let this go backwards!!
|
||||||
|
if (mobj->threshold != 0)
|
||||||
|
can_id += (mobj->threshold & UINT8_MAX);
|
||||||
|
|
||||||
mobj->renderflags = 0;
|
mobj->renderflags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12940,17 +12946,15 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
|
||||||
}
|
}
|
||||||
case MT_SPRAYCAN:
|
case MT_SPRAYCAN:
|
||||||
{
|
{
|
||||||
if (nummapspraycans)
|
if (nummapspraycans == UINT8_MAX)
|
||||||
{
|
{
|
||||||
if (nummapspraycans != UINT8_MAX)
|
|
||||||
nummapspraycans++;
|
|
||||||
|
|
||||||
P_RemoveMobj(mobj);
|
P_RemoveMobj(mobj);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
P_SetScale(mobj, mobj->destscale = 2*mobj->scale);
|
P_SetScale(mobj, mobj->destscale = 2*mobj->scale);
|
||||||
|
|
||||||
|
mobj->threshold = nummapspraycans;
|
||||||
P_SprayCanInit(mobj);
|
P_SprayCanInit(mobj);
|
||||||
nummapspraycans++;
|
nummapspraycans++;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -816,7 +816,8 @@ static void P_SpawnMapThings(boolean spawnemblems)
|
||||||
|
|
||||||
Z_Free(loopends);
|
Z_Free(loopends);
|
||||||
|
|
||||||
if (spawnemblems)
|
if (spawnemblems
|
||||||
|
&& gametype != GT_TUTORIAL)
|
||||||
{
|
{
|
||||||
const UINT8 recommendedcans =
|
const UINT8 recommendedcans =
|
||||||
#ifdef DEVELOP
|
#ifdef DEVELOP
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue