From 9a6aeaaa560aa100ad08d799947c687d58c3b181 Mon Sep 17 00:00:00 2001 From: NepDisk <16447892+NepDisk@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:30:22 -0400 Subject: [PATCH] Allow ACS to call linedef specials as functions --- extras/gdcc/inc/ACS/rrspecial.acs | 145 +++++++++++++++--------------- src/k_acs-func.c | 10 +-- src/k_acs.c | 96 ++++++++++++++++++-- src/k_acs.h | 12 --- src/p_spec.c | 2 +- 5 files changed, 164 insertions(+), 101 deletions(-) diff --git a/extras/gdcc/inc/ACS/rrspecial.acs b/extras/gdcc/inc/ACS/rrspecial.acs index 6a1e23e09..46d0f6e4f 100644 --- a/extras/gdcc/inc/ACS/rrspecial.acs +++ b/extras/gdcc/inc/ACS/rrspecial.acs @@ -76,93 +76,88 @@ // Ideally would implement as many as possible. special - int 400:Floor_SetHeightTexture(2,3), // tag, height[, texture] - int 401:Ceiling_SetHeightTexture(2,3), // tag, height[, texture] - int 402:Light_ChangeToValue(2), // tag, value - int 403:Floor_Move(3,5), // tag, height, speed[, texture, script] - int 404:Ceiling_Move(3,5), // tag, height, speed[, texture, script] - int 405:Floor_MoveByOffset(3,4), // tag, offset, speed[, instant] + int 400:Floor_SetHeightTexture(3), - int 407:Ceiling_MoveByOffset(3,4), // tag, offset, speed[, instant] + int 402:Light_Copy(2), + int 403:Floor_Move(5), - int 409:Sector_ChangeTag(2), // old tag, new tag - int 410:Line_ChangeFrontSectorTag(2), // line tag, new tag + int 405:Floor_MoveByOffset(5), - int 411:Sector_StopMovement(1), // tag - int 412:Thing_Teleport(2, 5), // thing tag, sector tag[, silent, keep angle, keep speed]. Relative teleport is now a separate function. + int 408:Sector_SetFlats(2), + int 409:Sector_ChangeTag(3), + int 410:Line_ChangeFrontSectorTag(2), - // TODO: split all these damn features up into separate functions, instead of optional variables - int 413:Level_SetMusic(1, 12), // name[, track, loop, local, reload reset, force reset, position, position is offset, fade out time, fade in time, fade out vol, fade in vol] + int 411:Sector_StopMovement(1), + int 412:Thing_Teleport(5), + int 413:Level_SetMusic(1, 7), + int 414:Thing_PlaySound(4), + int 415:Console_Execute(1), + int 416:Light_Flicker(5), + int 417:Light_Pulse(5), + int 418:Light_BlinkUnsynced(6), + int 419:Light_Blink(6), + int 420:Light_Fade(4), + int 421:Light_Stop(1), + int 422:Player_CutAwayView(2, 3), + int 423:Level_SetSky(1, 2), + int 424:Level_SetWeather(1, 2), + int 425:Thing_SetState(1), + int 426:Thing_Stop(0, 1), + int 427:Player_AddScore(1), + int 428:FOF_StartMovement(2, 5), + int 429:Sector_Crush(4), - int 414:Thing_PlaySound(1, 3), // name[, local, origin enum]. Doing it from a sector is now a separate function. -// int 415:Console_Execute(1), // script id - int 416:Light_Flicker(2, 4), // tag, value a[, value b, frequency] - int 417:Light_Pulse(2, 4), // tag, value a[, value b, frequency] - int 418:Light_BlinkUnsynced(4, 5), // tag, low time, hi time, value a[, value b] - int 419:Light_Blink(4, 5), // tag, low time, hi time, value a[, value b] - int 420:Light_Fade(3, 5), // tag, value, speed[, speed is tics, no interrupt] - int 421:Light_Stop(1), // tag - int 422:Player_CutAwayView(2, 3), // tid, tics[, pitch] - int 423:Level_SetSky(1, 2), // texture[, global] - int 424:Level_SetWeather(1, 2), // effect[, global] - int 425:Thing_SetState(1), // string - int 426:Thing_Stop(0, 1), // [sector] - int 427:Player_AddScore(1), // amount - int 428:FOF_StartMovement(8, 9), // tag, bottom low, bottom hi, top low, top hi, speed, start delay, swap delay[, invert] - int 429:Ceiling_Crush(2, 3), // tag, speed[, constant] - int 430:Floor_Crush(2, 3), // tag, speed[, constant] - int 431:Sector_Crush(2, 3), // tag, speed[, constant] -// int 432:Thing_Set2D(1), // bool - int 433:Thing_SetFlip(1), // bool -// int 434:Player_CustomPower(?), - int 435:Scroll_Change(3), // tag, dir, speed - int 436:FOF_Shatter(2), // target, control - int 437:Player_DisableControl(1, 2), // time[, allowjump] - int 438:Thing_SetScale(1), // size - int 439:Line_CopyTextures(1, 2), // tag[, existing] +// int 432:Thing_Set2D(1), + int 433:Thing_SetFlip(1), +// int 434:Player_CustomPower(2), + int 435:Scroll_Change(2), + int 436:FOF_Shatter(2), + int 437:Player_DisableControl(1, 2), + int 438:Thing_SetScale(1), + int 439:Line_CopyTextures(1, 3), // int 440:Level_StartMetalSonicRace(0), - int 441:SetUnlockableTrigger(1), // ID - int 442:Sector_NextThingState(2, 3), // tag, type[, state] - int 443:Lua_Execute(1), // script - int 444:Earthquake(1, 2), // tics[, intensity] - int 445:FOF_SetExists(2, 3), // target, control[, exists] - int 446:FOF_Crumble(2, 3), // target, control[, options] - int 447:Sector_SetColormap(2, 8), // tag, light[, fade, extra, flags, force light, force fade, force extra] - int 448:SetSkyboxViewpoint(1, 2), // viewpoint ID[, global]. Center point is now a separate function - int 449:SetBossActive(1, 2), // boss ID[, active?] - int 450:ACS_ExecuteAlways(1,4), // script[, arg1, arg2, arg3] - int 451:ACS_ExecuteRandomAlways(2,5), // script low, script high[, arg1, arg2, arg3] - int 452:FOF_SetAlpha(3, 5), // target, control, alpha[, add, update flags] - int 453:FOF_Fade(4, 5), // target, control, alpha, time[, options] - int 454:FOF_StopFade(2, 3), // target, control[, interrupt] -// int 455:Sector_FadeColormap(?), // TODO - int 456:Sector_StopColormapFade(1), // tag - int 457:Thing_StartTracking(5), // tag, tolerance, time, script, continue + int 441:SetUnlockableTrigger(1), + int 442:Sector_NextThingState(4), + int 443:Lua_Execute(1, 8), + int 444:Earthquake(1, 3), + int 445:FOF_SetExists(2, 3), + int 446:FOF_Crumble(2, 3), + int 447:Sector_SetColormap(2, 3), + int 448:SetSkyboxViewpoint(3, 4), + int 449:SetBossActive(1, 2), + int 450:Line_Execute(1), + int 451:Line_ExecuteRandom(2), + int 452:FOF_SetAlpha(4), + int 453:FOF_Fade(5), + int 454:FOF_StopFade(2, 3), + int 455:Sector_FadeColormap(4), + int 456:Sector_StopColormapFade(1), + int 457:Thing_StartTracking(3, 5), int 458:Thing_StopTracking(0), - int 459:Prompt_Open(1, 3), // prompt[, allow control, close script]. Closing is now a separate function. - int 460:Player_AddRings(1, 2), // amount[, freq] - int 461:Thing_Spawn(4, 5), // type, x, y, z[, angle]. Randomized coordinates can be handled by code. + int 459:Prompt_Execute(4), + int 460:Player_AddRings(2, 3), + int 461:Thing_Spawn(5, 9), int 462:Level_Stopwatch(0), int 463:Thing_Dye(1), // color -// int 464:TriggerEggCapsule(1, 2), // capsule ID[, end level] +// int 464:TriggerEggCapsule(1, 2), - int 466:Level_SetFailed(0, 1), // [success?] + int 466:Level_SetFailed(1), - int 480:Polyobj_DoorSlide(5), // po, speed, angle, dist, delay - int 481:Polyobj_DoorSwing(4), // po, speed, angle, delay - int 482:Polyobj_Move(4), // po, speed, angle, dist - int 483:Polyobj_OR_Move(4), // po, speed, angle, dist - int 484:Polyobj_RotateRight(3), // po, speed, angle - int 485:Polyobj_OR_RotateRight(3), // po, speed, angle - int 486:Polyobj_RotateLeft(3), // po, speed, angle - int 487:Polyobj_OR_RotateLeft(3), // po, speed, angle - int 488:Polyobj_MoveByWaypoints(4), // po, speed, sequence[, options] - int 489:Polyobj_InvisibleIntangible(1, 2), // po[, just visibility] - int 490:Polyobj_VisibleTangible(1, 2), // po[, just visibility] - int 491:Polyobj_SetAlpha(2, 3), // po, alpha[, add] - int 492:Polyobj_FadeAlpha(2, 3), // po, alpha, speed[, options] + int 480:Polyobj_DoorSlide(5), + int 481:Polyobj_DoorSwing(4), + int 482:Polyobj_Move(4), + int 483:Polyobj_OR_Move(4), + int 484:Polyobj_RotateRight(3), + int 485:Polyobj_OR_RotateRight(3), + int 486:Polyobj_RotateLeft(3), + int 487:Polyobj_OR_RotateLeft(3), + int 488:Polyobj_MoveByWaypoints(4), + int 489:Polyobj_InvisibleIntangible(1, 2), + int 490:Polyobj_VisibleTangible(1, 2), + int 491:Polyobj_SetAlpha(2, 3), + int 492:Polyobj_FadeAlpha(2, 3), - int 499:Sector_ToggleWaypoints(0, 1), // [enable?] + int 499:Sector_ToggleWaypoints(1, 2), // internal functions have negative values int -1:GetLineUDMFInt(2, int, str), diff --git a/src/k_acs-func.c b/src/k_acs-func.c index ca5e8af08..f7521e502 100644 --- a/src/k_acs-func.c +++ b/src/k_acs-func.c @@ -174,7 +174,7 @@ static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type) --------------------------------------------------*/ static bool ACS_ActivatorIsLocal(ACSVM_Thread *thread) { - acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread); + activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread); if ((info != NULL) && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) @@ -394,7 +394,7 @@ bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wo --------------------------------------------------*/ bool ACS_CF_LineSide(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC) { - acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread); + activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread); (void)argV; (void)argC; @@ -411,7 +411,7 @@ bool ACS_CF_LineSide(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word ar --------------------------------------------------*/ bool ACS_CF_ClearLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC) { - acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread); + activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread); (void)argV; (void)argC; @@ -537,7 +537,7 @@ bool ACS_CF_Timer(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC) --------------------------------------------------*/ bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC) { - acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread); + activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread); ACSVM_MapScope *map = NULL; ACSVM_String *str = NULL; @@ -711,7 +711,7 @@ bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W --------------------------------------------------*/ bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC) { - acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread); + activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread); mtag_t tag = 0; INT32 spec = 0; diff --git a/src/k_acs.c b/src/k_acs.c index 883b7bfc9..95a4b7e45 100644 --- a/src/k_acs.c +++ b/src/k_acs.c @@ -416,6 +416,85 @@ static bool ACS_EnvCheckTag(ACSVM_Environment const *env, ACSVM_Word type, ACSVM return true; } +/*-------------------------------------------------- + static ACSVM_Word ACS_EnvCallSpecial(ACSVM_Environment const *env, ACSVM_Thread *thread, ACSVM_Word spec, ACSVM_Word const *argV, ACSVM_Word argC) + + ACSVM Environment hook. Activates a special + function straight from the script rather than + a linedef. + + Input Arguments:- + env - The ACS environment data. + thread - The thread that is executing the special. + spec - The special ID to execute. + argV - Array containing the arguments given from the script. + argC - The number of entries in argV. + + Return:- + 1 when successful, otherwise 0. +--------------------------------------------------*/ +static ACSVM_Word ACS_EnvCallSpecial(ACSVM_Environment *env, ACSVM_Thread *thread, ACSVM_Word spec, ACSVM_Word const *argV, ACSVM_Word argC) +{ + activator_t *info = ACSVM_Thread_GetInfo(thread); + ACSVM_MapScope *map = ACSVM_Thread_GetScopeMap(thread); + + INT32 args[NUMLINEARGS] = {0}; + char *stringargs[NUMLINESTRINGARGS] = {0}; + size_t numStringArgs = 0; + size_t i = 0; + + (void)env; + + // This needs manually set, as ACS just uses indicies in the + // compiled string table and not actual strings, and SRB2 has + // separate args and stringargs, so there's no way to + // properly distinguish them. + switch (spec) + { + case 442: + numStringArgs = 2; + break; + case 413: + case 414: + case 415: + case 423: + case 425: + case 443: + case 459: + case 461: + case 463: + case 469: + numStringArgs = 1; + break; + default: + break; + } + + for (; i < numStringArgs; i++) + { + ACSVM_String *strPtr = ACSVM_MapScope_GetString(map, argV[i]); + const char *str = ACSVM_String_GetStr(strPtr); + size_t strLen = ACSVM_String_GetLen(strPtr); + + stringargs[i] = Z_Malloc(strLen + 1, PU_STATIC, NULL); + M_Memcpy(stringargs[i], str, strLen + 1); + } + + for (; i < min(argC, NUMLINEARGS); i++) + { + args[i - numStringArgs] = argV[i]; + } + + P_ProcessSpecial(info, spec, args, stringargs); + + for (i = 0; i < numStringArgs; i++) + { + Z_Free(stringargs[i]); + } + + return 1; +} + /*-------------------------------------------------- static void ACS_ThrDestruct(ACSVM_Thread *thread) @@ -430,7 +509,7 @@ static bool ACS_EnvCheckTag(ACSVM_Environment const *env, ACSVM_Word type, ACSVM --------------------------------------------------*/ static void ACS_ThrDestruct(ACSVM_Thread *thread) { - acs_threadinfo_t *info = ACSVM_Thread_GetInfo(thread); + activator_t *info = ACSVM_Thread_GetInfo(thread); if (info != NULL) { @@ -453,7 +532,7 @@ static void ACS_ThrDestruct(ACSVM_Thread *thread) --------------------------------------------------*/ static void ACS_ThrStart(ACSVM_Thread *thread, void *data) { - acs_threadinfo_t *activator = NULL; + activator_t *activator = NULL; ACSVM_Thread_SetResult(thread, 1); @@ -461,11 +540,11 @@ static void ACS_ThrStart(ACSVM_Thread *thread, void *data) { // Create an empty one, to reduce NULL checks. // Might not be necessary. - activator = Z_Calloc(sizeof(acs_threadinfo_t), PU_STATIC, NULL); + activator = Z_Calloc(sizeof(activator_t), PU_STATIC, NULL); } else { - activator = (acs_threadinfo_t *)data; + activator = (activator_t *)data; } ACSVM_Thread_SetInfo(thread, activator); @@ -512,6 +591,7 @@ void ACS_Init(void) funcs.ctor = ACS_EnvConstruct; funcs.loadModule = ACS_EnvLoadModule; funcs.checkTag = ACS_EnvCheckTag; + funcs.callSpecImpl = ACS_EnvCallSpecial; funcs.allocThread = ACS_EnvAllocThread; ACSenv = ACSVM_AllocEnvironment(&funcs, NULL); @@ -661,13 +741,13 @@ void ACS_RunPlayerEnterScript(player_t *player) ACSVM_HubScope *hub = NULL; ACSVM_MapScope *map = NULL; - acs_threadinfo_t *activator = NULL; + activator_t *activator = NULL; global = ACSVM_Environment_GetGlobalScope(ACSenv, 0); hub = ACSVM_GlobalScope_GetHubScope(global, 0); map = ACSVM_HubScope_GetMapScope(hub, 0); - activator = Z_Calloc(sizeof(acs_threadinfo_t), PU_STATIC, NULL); + activator = Z_Calloc(sizeof(activator_t), PU_STATIC, NULL); P_SetTarget(&activator->mo, player->mo); @@ -725,13 +805,13 @@ void ACS_RunLapScript(mobj_t *mo, line_t *line) ACSVM_HubScope *hub = NULL; ACSVM_MapScope *map = NULL; - acs_threadinfo_t *activator = NULL; + activator_t *activator = NULL; global = ACSVM_Environment_GetGlobalScope(ACSenv, 0); hub = ACSVM_GlobalScope_GetHubScope(global, 0); map = ACSVM_HubScope_GetMapScope(hub, 0); - activator = Z_Calloc(sizeof(acs_threadinfo_t), PU_STATIC, NULL); + activator = Z_Calloc(sizeof(activator_t), PU_STATIC, NULL); P_SetTarget(&activator->mo, mo); activator->line = line; diff --git a/src/k_acs.h b/src/k_acs.h index f8efecdc4..0f764d422 100644 --- a/src/k_acs.h +++ b/src/k_acs.h @@ -50,18 +50,6 @@ typedef enum ACS_TAGTYPE_SECTOR, } acs_tagType_e; -// -// Thread activator info -// -typedef struct -{ - mobj_t *mo; // Object that activated this thread. - line_t *line; // Linedef that activated this thread. - UINT8 side; // Front / back side of said linedef. - sector_t *sector; // Sector that activated this thread. - polyobj_t *po; // Polyobject that activated this thread. -} acs_threadinfo_t; - /*-------------------------------------------------- ACSVM_Environment *ACS_GetEnvironment(void); diff --git a/src/p_spec.c b/src/p_spec.c index 4f77a1d4f..5cf76fcd0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5188,7 +5188,7 @@ static void P_EvaluateOldSectorSpecial(player_t *player, sector_t *sector, secto if ((gametyperules & GTR_CIRCUIT) && (player->exiting == 0) && !(player->pflags & PF_HITFINISHLINE)) { K_HandleLapIncrement(player, true); - ACS_RunLapScript(player->mo, line); + //ACS_RunLapScript(player->mo, line); // Theres no line so what is this supposed to run on. player->pflags |= PF_HITFINISHLINE; } break;