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 257fc5e44..5d1efa3c7 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 14c4aec8d..80e772f1e 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); @@ -657,13 +737,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); @@ -721,13 +801,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 63c4745a3..41cbe8ec5 100644 --- a/src/k_acs.h +++ b/src/k_acs.h @@ -55,12 +55,33 @@ typedef enum // 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; + 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. + boolean fromLineSpecial; // Called from P_ProcessLineSpecial. +} activator_t; + + +/*-------------------------------------------------- + void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs); + + Runs a numbered special action. Can be called + by both linedefs and ACS scripts. + + Input Arguments:- + activator - Struct containing information on what activated this special. + special - Special ID. + args - Array of the args. + stringargs - Array of the string args. + + Return:- + N/A +--------------------------------------------------*/ + +void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs); + /*-------------------------------------------------- ACSVM_Environment *ACS_GetEnvironment(void); diff --git a/src/p_spec.c b/src/p_spec.c index 498a2586a..84cd80b18 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2203,20 +2203,64 @@ static mobj_t* P_FindObjectTypeFromTag(mobjtype_t type, mtag_t tag) */ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { + activator_t *activator = NULL; + + if (line == NULL) + { + // No line to activate + return; + } + + activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL); + I_Assert(activator != NULL); + + P_SetTarget(&activator->mo, mo); + activator->line = line; + activator->sector = callsec; + activator->fromLineSpecial = true; + + P_ProcessSpecial(activator, line->special, line->args, line->stringargs); + Z_Free(activator); +} + +void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs) +{ + line_t *line = activator->line; // If called from a linedef executor, this is the control sector linedef. If from a script, then it's the actual activator. + mobj_t *mo = activator->mo; + sector_t *callsec = activator->sector; + + // All of these conditions being met means this is a binary map using a linedef executor. + const boolean backwardsCompat = (!udmf && activator->fromLineSpecial && line != NULL); + INT32 secnum = -1; - mobj_t *bot = NULL; + + // + // TODO: Too many specials are tied to a linedef existing, + // even after UDMF cleanups. We'll need to remove all of the + // (line == NULL) guards if we want these to be useful for ACS. + // // note: only commands with linedef types >= 400 && < 500 can be used - switch (line->special) + switch (special) { case 400: // Set tagged sector's heights/flats - if (line->args[1] != TMP_CEILING) - EV_DoFloor(line->args[0], line, instantMoveFloorByFrontSector); - if (line->args[1] != TMP_FLOOR) - EV_DoCeiling(line->args[0], line, instantMoveCeilingByFrontSector); + if (line == NULL) + { + break; // TODO + } + + if (args[1] != TMP_CEILING) + EV_DoFloor(args[0], line, instantMoveFloorByFrontSector); + if (args[1] != TMP_FLOOR) + EV_DoCeiling(args[0], line, instantMoveCeilingByFrontSector); break; case 402: // Copy light level to tagged sectors + if (line == NULL) + { + break; // TODO + } + { INT16 newlightlevel; INT16 newfloorlightlevel, newceilinglightlevel; @@ -2231,7 +2275,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) newfloorlightsec = line->frontsector->floorlightsec; newceilinglightsec = line->frontsector->ceilinglightsec; - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { if (sectors[secnum].lightingdata) { @@ -2240,15 +2284,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) sectors[secnum].lightingdata = NULL; } - if (!(line->args[1] & TMLC_NOSECTOR)) + if (!(args[1] & TMLC_NOSECTOR)) sectors[secnum].lightlevel = newlightlevel; - if (!(line->args[1] & TMLC_NOFLOOR)) + + if (!(args[1] & TMLC_NOFLOOR)) { sectors[secnum].floorlightlevel = newfloorlightlevel; sectors[secnum].floorlightabsolute = newfloorlightabsolute; sectors[secnum].floorlightsec = newfloorlightsec; } - if (!(line->args[1] & TMLC_NOCEILING)) + + if (!(args[1] & TMLC_NOCEILING)) { sectors[secnum].ceilinglightlevel = newceilinglightlevel; sectors[secnum].ceilinglightabsolute = newceilinglightabsolute; @@ -2259,26 +2305,41 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 403: // Move planes by front sector - if (line->args[1] != TMP_CEILING) - EV_DoFloor(line->args[0], line, moveFloorByFrontSector); - if (line->args[1] != TMP_FLOOR) - EV_DoCeiling(line->args[0], line, moveCeilingByFrontSector); + if (line == NULL) + { + break; // TODO + } + + if (args[1] != TMP_CEILING) + EV_DoFloor(args[0], line, moveFloorByFrontSector); + if (args[1] != TMP_FLOOR) + EV_DoCeiling(args[0], line, moveCeilingByFrontSector); break; case 405: // Move planes by distance - if (line->args[1] != TMP_CEILING) - EV_DoFloor(line->args[0], line, moveFloorByDistance); - if (line->args[1] != TMP_FLOOR) - EV_DoCeiling(line->args[0], line, moveCeilingByDistance); + if (line == NULL) + { + break; // TODO + } + + if (args[1] != TMP_CEILING) + EV_DoFloor(args[0], line, moveFloorByDistance); + if (args[1] != TMP_FLOOR) + EV_DoCeiling(args[0], line, moveCeilingByDistance); break; case 408: // Set flats { - TAG_ITER_SECTORS(line->args[0], secnum) + if (line == NULL) { - if (line->args[1] != TMP_CEILING) + break; // TODO + } + + TAG_ITER_SECTORS(args[0], secnum) + { + if (args[1] != TMP_CEILING) sectors[secnum].floorpic = line->frontsector->floorpic; - if (line->args[1] != TMP_FLOOR) + if (args[1] != TMP_FLOOR) sectors[secnum].ceilingpic = line->frontsector->ceilingpic; } break; @@ -2287,11 +2348,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { - mtag_t newtag = line->args[1]; + mtag_t newtag = args[1]; - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { - switch (line->args[2]) + switch (args[2]) { case TMT_ADD: Tag_SectorAdd(secnum, newtag); @@ -2310,10 +2371,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 410: // Change front sector's tag { - mtag_t newtag = line->args[1]; + mtag_t newtag; + + if (line == NULL) + { + break; // This one is reasonable to have based on the activator. + } + + newtag = args[1]; secnum = (UINT32)(line->frontsector - sectors); - switch (line->args[2]) + switch (args[2]) { case TMT_ADD: Tag_SectorAdd(secnum, newtag); @@ -2330,7 +2398,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } case 411: // Stop floor/ceiling movement in tagged sector(s) - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { if (sectors[secnum].floordata) { @@ -2364,13 +2432,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!mo) // nothing to teleport return; - if (line->args[1] & TMT_RELATIVE) // Relative silent teleport + if (args[1] & TMT_RELATIVE) // Relative silent teleport { fixed_t x, y, z; - x = line->args[2] << FRACBITS; - y = line->args[3] << FRACBITS; - z = line->args[4] << FRACBITS; + x = args[2] << FRACBITS; + y = args[3] << FRACBITS; + z = args[4] << FRACBITS; P_UnsetThingPosition(mo); mo->x += x; @@ -2401,17 +2469,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) angle_t angle; boolean silent, keepmomentum; - dest = P_FindObjectTypeFromTag(MT_TELEPORTMAN, line->args[0]); + dest = P_FindObjectTypeFromTag(MT_TELEPORTMAN, args[0]); if (!dest) return; - angle = (line->args[1] & TMT_KEEPANGLE) ? mo->angle : dest->angle; - silent = !!(line->args[1] & TMT_SILENT); - keepmomentum = !!(line->args[1] & TMT_KEEPMOMENTUM); + angle = (args[1] & TMT_KEEPANGLE) ? mo->angle : dest->angle; + silent = !!(args[1] & TMT_SILENT); + keepmomentum = !!(args[1] & TMT_KEEPMOMENTUM); - if (bot) - P_Teleport(bot, dest->x, dest->y, dest->z, angle, !silent, keepmomentum); P_Teleport(mo, dest->x, dest->y, dest->z, angle, !silent, keepmomentum); + if (!silent) S_StartSound(dest, sfx_mixup); // Play the 'bowrwoosh!' sound } @@ -2420,18 +2487,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 413: // Change music // console player only unless TMM_ALLPLAYERS is set - if ((line->args[0] & TMM_ALLPLAYERS) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) + if ((args[0] & TMM_ALLPLAYERS) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) { - boolean musicsame = (!line->stringargs[0] || !line->stringargs[0][0] || !strnicmp(line->stringargs[0], S_MusicName(), 7)); - UINT16 tracknum = (UINT16)max(line->args[6], 0); - INT32 position = (INT32)max(line->args[1], 0); - UINT32 prefadems = (UINT32)max(line->args[2], 0); - UINT32 postfadems = (UINT32)max(line->args[3], 0); - UINT8 fadetarget = (UINT8)max(line->args[4], 0); - INT16 fadesource = (INT16)max(line->args[5], -1); + boolean musicsame = (!stringargs[0] || !stringargs[0][0] || !strnicmp(stringargs[0], S_MusicName(), 7)); + UINT16 tracknum = (UINT16)max(args[6], 0); + INT32 position = (INT32)max(args[1], 0); + UINT32 prefadems = (UINT32)max(args[2], 0); + UINT32 postfadems = (UINT32)max(args[3], 0); + UINT8 fadetarget = (UINT8)max(args[4], 0); + INT16 fadesource = (INT16)max(args[5], -1); // Seek offset from current song position - if (line->args[0] & TMM_OFFSET) + if (args[0] & TMM_OFFSET) { // adjust for loop point if subtracting if (position < 0 && S_GetMusicLength() && @@ -2443,7 +2510,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } // Fade current music to target volume (if music won't be changed) - if ((line->args[0] & TMM_FADE) && fadetarget && musicsame) + if ((args[0] & TMM_FADE) && fadetarget && musicsame) { // 0 fadesource means fade from current volume. // meaning that we can't specify volume 0 as the source volume -- this starts at 1. @@ -2461,29 +2528,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Change the music and apply position/fade operations else { - if (!line->stringargs[0]) + if (!stringargs[0]) break; - strncpy(mapmusname, line->stringargs[0], 7); + strncpy(mapmusname, stringargs[0], 7); mapmusname[6] = 0; mapmusflags = tracknum & MUSIC_TRACKMASK; - if (!(line->args[0] & TMM_NORELOAD)) + if (!(args[0] & TMM_NORELOAD)) mapmusflags |= MUSIC_RELOADRESET; - if (line->args[0] & TMM_FORCERESET) + if (args[0] & TMM_FORCERESET) mapmusflags |= MUSIC_FORCERESET; mapmusposition = position; mapmusresume = 0; - S_ChangeMusicEx(mapmusname, mapmusflags, !(line->args[0] & TMM_NOLOOP), position, - !(line->args[0] & TMM_FADE) ? prefadems : 0, - !(line->args[0] & TMM_FADE) ? postfadems : 0); + S_ChangeMusicEx(mapmusname, mapmusflags, !(args[0] & TMM_NOLOOP), position, + !(args[0] & TMM_FADE) ? prefadems : 0, + !(args[0] & TMM_FADE) ? postfadems : 0); - if (!(line->args[0] & TMM_NOCREDIT)) + if (!(args[0] & TMM_NOCREDIT)) S_ShowMusicCredit(); - if ((line->args[0] & TMM_FADE) && fadetarget) + if ((args[0] & TMM_FADE) && fadetarget) { if (!postfadems) S_SetInternalMusicVolume(fadetarget); @@ -2498,46 +2565,46 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 414: // Play SFX - P_PlaySFX(line->stringargs[0] ? get_number(line->stringargs[0]) : sfx_None, mo, callsec, line->args[2], line->args[0], line->args[1]); + P_PlaySFX(stringargs[0] ? get_number(stringargs[0]) : sfx_None, mo, callsec, args[2], args[0], args[1]); break; case 415: // Run a script if (cv_runscripts.value) { - lumpnum_t lumpnum = W_CheckNumForName(line->stringargs[0]); + lumpnum_t lumpnum = W_CheckNumForName(stringargs[0]); if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0) - CONS_Debug(DBG_SETUP, "Line type 415 Executor: script lump %s not found/not valid.\n", line->stringargs[0]); + CONS_Debug(DBG_SETUP, "Line type 415 Executor: script lump %s not found/not valid.\n", stringargs[0]); else COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); } break; case 416: // Spawn adjustable fire flicker - TAG_ITER_SECTORS(line->args[0], secnum) - P_SpawnAdjustableFireFlicker(§ors[secnum], line->args[2], - line->args[3] ? sectors[secnum].lightlevel : line->args[4], line->args[1]); + TAG_ITER_SECTORS(args[0], secnum) + P_SpawnAdjustableFireFlicker(§ors[secnum], args[2], + args[3] ? sectors[secnum].lightlevel : args[4], args[1]); break; case 417: // Spawn adjustable glowing light - TAG_ITER_SECTORS(line->args[0], secnum) - P_SpawnAdjustableGlowingLight(§ors[secnum], line->args[2], - line->args[3] ? sectors[secnum].lightlevel : line->args[4], line->args[1]); + TAG_ITER_SECTORS(args[0], secnum) + P_SpawnAdjustableGlowingLight(§ors[secnum], args[2], + args[3] ? sectors[secnum].lightlevel : args[4], args[1]); break; case 418: // Spawn adjustable strobe flash - TAG_ITER_SECTORS(line->args[0], secnum) - P_SpawnAdjustableStrobeFlash(§ors[secnum], line->args[3], - (line->args[4] & TMB_USETARGET) ? sectors[secnum].lightlevel : line->args[5], - line->args[1], line->args[2], line->args[4] & TMB_SYNC); + TAG_ITER_SECTORS(args[0], secnum) + P_SpawnAdjustableStrobeFlash(§ors[secnum], args[3], + (args[4] & TMB_USETARGET) ? sectors[secnum].lightlevel : args[5], + args[1], args[2], args[4] & TMB_SYNC); break; case 420: // Fade light levels in tagged sectors to new value - P_FadeLight(line->args[0], line->args[1], line->args[2], line->args[3] & TMF_TICBASED, line->args[3] & TMF_OVERRIDE, line->args[3] & TMF_RELATIVE); + P_FadeLight(args[0], args[1], args[2], args[3] & TMF_TICBASED, args[3] & TMF_OVERRIDE, args[3] & TMF_RELATIVE); break; case 421: // Stop lighting effect in tagged sectors - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) if (sectors[secnum].lightingdata) { P_RemoveThinker(&((thinkerdata_t *)sectors[secnum].lightingdata)->thinker); @@ -2553,7 +2620,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens return; - altview = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, line->args[0]); + altview = P_FindObjectTypeFromTag(MT_ALTVIEWMAN, args[0]); if (!altview || !altview->spawnpoint) return; @@ -2564,10 +2631,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else { P_SetTarget(&mo->player->awayviewmobj, altview); - mo->player->awayviewtics = line->args[1]; + mo->player->awayviewtics = args[1]; } - aim = udmf ? altview->spawnpoint->pitch : line->args[2]; + aim = udmf ? altview->spawnpoint->pitch : args[2]; aim = (aim + 360) % 360; aim *= (ANGLE_90>>8); aim /= 90; @@ -2580,24 +2647,24 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 423: // Change Sky - if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || line->args[1]) - P_SetupLevelSky(line->stringargs[0], line->args[1]); + if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || args[1]) + P_SetupLevelSky(stringargs[0], args[1]); break; case 424: // Change Weather - if (line->args[1]) + if (args[1]) { - globalweather = (UINT8)(line->args[0]); + globalweather = (UINT8)(args[0]); P_SwitchWeather(globalweather); } else if (mo && mo->player && P_IsLocalPlayer(mo->player)) - P_SwitchWeather(line->args[0]); + P_SwitchWeather(args[0]); break; case 425: // Calls P_SetMobjState on calling mobj if (mo && !mo->player) { - statenum_t state = line->stringargs[0] ? get_number(line->stringargs[0]) : S_NULL; + statenum_t state = stringargs[0] ? get_number(stringargs[0]) : S_NULL; if (state >= 0 && state < NUMSTATES) P_SetMobjState(mo, state); } @@ -2607,7 +2674,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!mo) return; - if (line->args[0]) + if (args[0]) { P_UnsetThingPosition(mo); mo->x = mo->subsector->sector->soundorg.x; @@ -2630,29 +2697,40 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 427: // Awards points if the mobj is a player if (mo && mo->player) - P_AddPlayerScore(mo->player, line->args[0]); + P_AddPlayerScore(mo->player, args[0]); break; case 428: // Start floating platform movement - EV_DoElevator(line->args[0], line, elevateContinuous); + if (line == NULL) + { + break; // TODO + } + + EV_DoElevator(args[0], line, elevateContinuous); break; case 429: // Crush planes once - if (line->args[1] == TMP_FLOOR) - EV_DoFloor(line->args[0], line, crushFloorOnce); + if (line == NULL) + { + break; // TODO + } + + if (args[1] == TMP_FLOOR) + EV_DoFloor(args[0], line, crushFloorOnce); else if (line->args[1] == TMP_CEILING) - EV_DoCrush(line->args[0], line, crushCeilOnce); + EV_DoCrush(args[0], line, crushCeilOnce); else - EV_DoCrush(line->args[0], line, crushBothOnce); + EV_DoCrush(args[0], line, crushBothOnce); break; case 433: // Flip/flop gravity. Works on pushables, too! - if (line->args[0]) + if (!mo) + return; + + if (args[0]) mo->flags2 &= ~MF2_OBJECTFLIP; else mo->flags2 |= MF2_OBJECTFLIP; - if (bot) - bot->flags2 = (bot->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); break; case 435: // Change scroller direction @@ -2660,10 +2738,20 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) scroll_t *scroller; thinker_t *th; - fixed_t length = R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); - fixed_t speed = line->args[1] << FRACBITS; - fixed_t dx = FixedMul(FixedMul(FixedDiv(line->dx, length), speed) >> SCROLL_SHIFT, CARRYFACTOR); - fixed_t dy = FixedMul(FixedMul(FixedDiv(line->dy, length), speed) >> SCROLL_SHIFT, CARRYFACTOR); + fixed_t length; + fixed_t speed; + fixed_t dx; + fixed_t dy; + + if (line == NULL) + { + break; // TODO + } + + length = R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); + speed = args[1] << FRACBITS; + dx = FixedMul(FixedMul(FixedDiv(line->dx, length), speed) >> SCROLL_SHIFT, CARRYFACTOR); + dy = FixedMul(FixedMul(FixedDiv(line->dy, length), speed) >> SCROLL_SHIFT, CARRYFACTOR); for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { @@ -2671,7 +2759,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) continue; scroller = (scroll_t *)th; - if (!Tag_Find(§ors[scroller->affectee].tags, line->args[0])) + if (!Tag_Find(§ors[scroller->affectee].tags, args[0])) continue; scroller->dx = dx; @@ -2682,8 +2770,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 436: // Shatter block remotely { - INT16 sectag = (INT16)(line->args[0]); - INT16 foftag = (INT16)(line->args[1]); + INT16 sectag = (INT16)(args[0]); + INT16 foftag = (INT16)(args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to crumble boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -2694,7 +2782,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Special type 436: Target sector #%d has no FOFs.\n", secnum); return; } @@ -2710,7 +2798,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!foundrover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Special type 436: Can't find a FOF control sector with tag %d\n", foftag); return; } } @@ -2720,10 +2808,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 437: // Disable Player Controls if (mo && mo->player) { - UINT16 fractime = (UINT16)(line->args[0]); + UINT16 fractime = (UINT16)(args[0]); if (fractime < 1) fractime = 1; //instantly wears off upon leaving - if (line->args[1]) + if (args[1]) fractime |= 1<<15; //more crazy &ing, as if music stuff wasn't enough mo->player->nocontrol = fractime; } @@ -2732,7 +2820,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 438: // Set player scale if (mo) { - mo->destscale = FixedDiv(line->args[0]<destscale = FixedDiv(args[0]<destscale < FRACUNIT/100) mo->destscale = FRACUNIT/100; } @@ -2741,8 +2829,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 439: // Set texture { size_t linenum; - side_t *set = &sides[line->sidenum[0]], *this; - boolean always = !(line->args[2]); // If args[2] is set: Only change mid texture if mid texture already exists on tagged lines, etc. + side_t *set, *this; + boolean always; + + if (line == NULL) + { + break; // TODO + } + + set = &sides[line->sidenum[0]]; + always = !(line->args[2]); // If args[2] is set: Only change mid texture if mid texture already exists on tagged lines, etc. for (linenum = 0; linenum < numlines; linenum++) { @@ -2781,13 +2877,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 441: // Trigger unlockable if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) { - INT32 trigid = line->args[0]; + INT32 trigid = args[0]; if (trigid < 0 || trigid > 31) // limited by 32 bit variable - CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", line->sidenum[0], trigid); + CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger: bad trigger ID %d\n", trigid); else { - unlocktriggers |= 1 << trigid; + UINT32 flag = 1 << trigid; + + if (unlocktriggers & flag) + { + // Execute one time only + break; + } + + unlocktriggers |= flag; // Unlocked something? if (M_UpdateUnlockablesAndExtraEmblems()) @@ -2797,29 +2901,26 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } } - - // Execute one time only - line->special = 0; break; case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors { - const mobjtype_t type = line->stringargs[0] ? get_number(line->stringargs[0]) : MT_NULL; + const mobjtype_t type = stringargs[0] ? get_number(stringargs[0]) : MT_NULL; statenum_t state = NUMSTATES; mobj_t *thing; if (type < 0 || type >= NUMMOBJTYPES) break; - if (!line->args[1]) + if (!args[1]) { - state = line->stringargs[1] ? get_number(line->stringargs[1]) : S_NULL; + state = stringargs[1] ? get_number(stringargs[1]) : S_NULL; if (state < 0 || state >= NUMSTATES) break; } - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { boolean tryagain; do { @@ -2829,7 +2930,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (thing->type != type) continue; - if (!P_SetMobjState(thing, line->args[1] ? thing->state->nextstate : state)) + if (!P_SetMobjState(thing, args[1] ? thing->state->nextstate : state)) { // mobj was removed tryagain = true; // snext is corrupt, we'll have to start over. break; @@ -2841,17 +2942,28 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } case 443: // Calls a named Lua function - if (line->stringargs[0]) + if (line == NULL) + { + break; + } + + if (stringargs[0]) + { + // TODO: This hook needs overhauled to insert the hook name from the proper stringargs[0], + // and to give activator_t userdata instead of loose arguments. LUA_HookLinedefExecute(line, mo, callsec); + } else - CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in stringarg0)\n", sizeu1(line-lines)); + { + CONS_Alert(CONS_WARNING, "Special 443 is missing the hook name of the Lua function to call! (This should be given in stringarg0)\n"); + } break; case 444: // Earthquake camera { - quake.intensity = line->args[1] << FRACBITS; - quake.radius = line->args[2] << FRACBITS; - quake.time = line->args[0]; + quake.intensity = args[1] << FRACBITS; + quake.radius = args[2] << FRACBITS; + quake.time = args[0]; quake.epicenter = NULL; /// \todo @@ -2865,8 +2977,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 445: // Force block disappear remotely (reappear if args[2] is set) { - INT16 sectag = (INT16)(line->args[0]); - INT16 foftag = (INT16)(line->args[1]); + INT16 sectag = (INT16)(args[0]); + INT16 foftag = (INT16)(args[1]); sector_t *sec; // Sector that the FOF is visible (or not visible) in ffloor_t *rover; // FOF to vanish/un-vanish boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -2878,7 +2990,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Special type 445 Executor: Target sector #%d has no FOFs.\n", secnum); return; } @@ -2891,7 +3003,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) oldflags = rover->fofflags; // Abracadabra! - if (line->args[2]) + if (args[2]) rover->fofflags |= FOF_EXISTS; else rover->fofflags &= ~FOF_EXISTS; @@ -2907,7 +3019,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!foundrover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Special type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } } @@ -2916,8 +3028,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 446: // Make block fall remotely (acts like FOF_CRUMBLE) { - INT16 sectag = (INT16)(line->args[0]); - INT16 foftag = (INT16)(line->args[1]); + INT16 sectag = (INT16)(args[0]); + INT16 foftag = (INT16)(args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to make fall down boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -2927,7 +3039,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mo) // NULL check player = mo->player; - if (line->args[2] & TMFR_NORETURN) // don't respawn! + if (args[2] & TMFR_NORETURN) // don't respawn! respawn = false; TAG_ITER_SECTORS(sectag, secnum) @@ -2936,7 +3048,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Special type 446 Executor: Target sector #%d has no FOFs.\n", secnum); return; } @@ -2946,8 +3058,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { foundrover = true; - if (line->args[2] & TMFR_CHECKFLAG) // FOF flags determine respawn ability instead? - respawn = !(rover->fofflags & FOF_NORETURN) ^ !!(line->args[2] & TMFR_NORETURN); // TMFR_NORETURN inverts + if (args[2] & TMFR_CHECKFLAG) // FOF flags determine respawn ability instead? + respawn = !(rover->fofflags & FOF_NORETURN) ^ !!(args[2] & TMFR_NORETURN); // TMFR_NORETURN inverts EV_StartCrumble(rover->master->frontsector, rover, (rover->fofflags & FOF_FLOATBOB), player, rover->alpha, respawn); } @@ -2955,7 +3067,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!foundrover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Special type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } } @@ -2969,50 +3081,62 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // -- Monster Iestyn 14/06/18 { extracolormap_t *source; - if (!udmf) + + if (backwardsCompat) + { source = sides[line->sidenum[0]].colormap_data; + } else { - if (!line->args[1]) + if (!args[1]) + { + if (line == NULL) + { + CONS_Debug(DBG_GAMELOGIC, "Special type 447 Executor: Can't find frontsector with source colormap!\n"); + return; + } source = line->frontsector->extra_colormap; + } else { - INT32 sourcesec = Tag_Iterate_Sectors(line->args[1], 0); + INT32 sourcesec = Tag_Iterate_Sectors(args[1], 0); if (sourcesec == -1) { - CONS_Debug(DBG_GAMELOGIC, "Line type 447 Executor: Can't find sector with source colormap (tag %d)!\n", line->args[1]); + CONS_Debug(DBG_GAMELOGIC, "Special type 447 Executor: Can't find sector with source colormap (tag %d)!\n", args[1]); return; } source = sectors[sourcesec].extra_colormap; } } - TAG_ITER_SECTORS(line->args[0], secnum) + + TAG_ITER_SECTORS(args[0], secnum) { if (sectors[secnum].colormap_protected) continue; P_ResetColormapFader(§ors[secnum]); - if (line->args[2] & TMCF_RELATIVE) + if (args[2] & TMCF_RELATIVE) { - extracolormap_t *target = (!udmf && (line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF) ? + extracolormap_t *target = (backwardsCompat && (line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap; // use back colormap instead of target sector - extracolormap_t *exc = R_AddColormaps( - target, - source, - line->args[2] & TMCF_SUBLIGHTR, - line->args[2] & TMCF_SUBLIGHTG, - line->args[2] & TMCF_SUBLIGHTB, - line->args[2] & TMCF_SUBLIGHTA, - line->args[2] & TMCF_SUBFADER, - line->args[2] & TMCF_SUBFADEG, - line->args[2] & TMCF_SUBFADEB, - line->args[2] & TMCF_SUBFADEA, - line->args[2] & TMCF_SUBFADESTART, - line->args[2] & TMCF_SUBFADEEND, - line->args[2] & TMCF_IGNOREFLAGS, - false); + extracolormap_t *exc = R_AddColormaps( + target, + source, + args[2] & TMCF_SUBLIGHTR, + args[2] & TMCF_SUBLIGHTG, + args[2] & TMCF_SUBLIGHTB, + args[2] & TMCF_SUBLIGHTA, + args[2] & TMCF_SUBFADER, + args[2] & TMCF_SUBFADEG, + args[2] & TMCF_SUBFADEB, + args[2] & TMCF_SUBFADEA, + args[2] & TMCF_SUBFADESTART, + args[2] & TMCF_SUBFADEEND, + args[2] & TMCF_IGNOREFLAGS, + false + ); if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) { @@ -3032,11 +3156,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { skybox_t skybox = {0}; - INT32 viewid = line->args[0]; - INT32 centerid = line->args[1]; + INT32 viewid = args[0]; + INT32 centerid = args[1]; // set viewpoint mobj - if (line->args[2] != TMS_CENTERPOINT) + if (args[2] != TMS_CENTERPOINT) { if (viewid >= 0 && viewid < 16) skybox.viewpoint = skyboxviewpnts[viewid]; @@ -3045,7 +3169,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } // set centerpoint mobj - if (line->args[2] != TMS_VIEWPOINT) + if (args[2] != TMS_VIEWPOINT) { if (centerid >= 0 && centerid < 16) skybox.centerpoint = skyboxcenterpnts[centerid]; @@ -3053,60 +3177,60 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) skybox.centerpoint = NULL; } - if (line->args[3]) // Applies to all players + if (args[3]) // Applies to all players { INT32 i; for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i]) - P_SwitchSkybox(line->args[2], &players[i], &skybox); + P_SwitchSkybox(args[2], &players[i], &skybox); } } else if (mo && mo->player) { - P_SwitchSkybox(line->args[2], mo->player, &skybox); + P_SwitchSkybox(args[2], mo->player, &skybox); } - CONS_Debug(DBG_GAMELOGIC, "Line type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n", + CONS_Debug(DBG_GAMELOGIC, "Special type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n", viewid, centerid, - ((line->args[2] == TMS_CENTERPOINT) ? "no" : "yes"), - ((line->args[2] == TMS_VIEWPOINT) ? "no" : "yes")); + ((args[2] == TMS_CENTERPOINT) ? "no" : "yes"), + ((args[2] == TMS_VIEWPOINT) ? "no" : "yes")); } break; case 449: // Enable bosses with parameter { - INT32 bossid = line->args[0]; + INT32 bossid = args[0]; if (bossid & ~15) // if any bits other than first 16 are set { CONS_Alert(CONS_WARNING, - M_GetText("Boss enable linedef has an invalid boss ID (%d).\nConsider changing it or removing it entirely.\n"), + M_GetText("Boss enable special has an invalid boss ID (%d).\nConsider changing it or removing it entirely.\n"), bossid); break; } - if (line->args[1]) + if (args[1]) { bossdisabled |= (1<args[0], mo, NULL); + P_LinedefExecute(args[0], mo, NULL); break; case 451: // Execute Random Linedef Executor { - INT32 rvalue1 = line->args[0]; - INT32 rvalue2 = line->args[1]; + INT32 rvalue1 = args[0]; + INT32 rvalue2 = args[1]; INT32 result; if (rvalue1 <= rvalue2) @@ -3120,9 +3244,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 452: // Set FOF alpha { - INT16 destvalue = (INT16)(line->args[2]); - INT16 sectag = (INT16)(line->args[0]); - INT16 foftag = (INT16)(line->args[1]); + INT16 destvalue = (INT16)(args[2]); + INT16 sectag = (INT16)(args[0]); + INT16 foftag = (INT16)(args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3146,7 +3270,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 // for relative alpha calc - if (!(line->args[3] & TMST_DONTDOTRANSLUCENT) && // do translucent + if (!(args[3] & TMST_DONTDOTRANSLUCENT) && // do translucent (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE !(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERPLANES) && @@ -3156,11 +3280,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, rover->alpha, - max(1, min(256, (line->args[3] & TMST_RELATIVE) ? rover->alpha + destvalue : destvalue)), + max(1, min(256, (args[3] & TMST_RELATIVE) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately false, NULL, // tic-based logic false, // do not handle FOF_EXISTS - !(line->args[3] & TMST_DONTDOTRANSLUCENT), // handle FOF_TRANSLUCENT + !(args[3] & TMST_DONTDOTRANSLUCENT), // handle FOF_TRANSLUCENT false, // do not handle lighting false, // do not handle colormap false, // do not handle collision @@ -3171,7 +3295,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!foundrover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Special type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } } @@ -3180,10 +3304,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 453: // Fade FOF { - INT16 destvalue = (INT16)(line->args[2]); - INT16 speed = (INT16)(line->args[3]); - INT16 sectag = (INT16)(line->args[0]); - INT16 foftag = (INT16)(line->args[1]); + INT16 destvalue = (INT16)(args[2]); + INT16 speed = (INT16)(args[3]); + INT16 sectag = (INT16)(args[0]); + INT16 foftag = (INT16)(args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3195,7 +3319,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Target sector #%d has no FOFs.\n", secnum); return; } @@ -3206,11 +3330,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) foundrover = true; // Prevent continuous execs from interfering on an existing fade - if (!(line->args[4] & TMFT_OVERRIDE) + if (!(args[4] & TMFT_OVERRIDE) && rover->fadingdata) //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); + CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); continue; } @@ -3218,21 +3342,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_AddFakeFloorFader(rover, secnum, j, destvalue, speed, - (line->args[4] & TMFT_TICBASED), // tic-based logic - (line->args[4] & TMFT_RELATIVE), // Relative destvalue - !(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS - !(line->args[4] & TMFT_DONTDOTRANSLUCENT), // do not handle FOF_TRANSLUCENT - !(line->args[4] & TMFT_DONTDOLIGHTING), // do not handle lighting - !(line->args[4] & TMFT_DONTDOCOLORMAP), // do not handle colormap - !(line->args[4] & TMFT_IGNORECOLLISION), // do not handle collision - (line->args[4] & TMFT_GHOSTFADE), // do ghost fade (no collision during fade) - (line->args[4] & TMFT_USEEXACTALPHA)); // use exact alpha values (for opengl) + (args[4] & TMFT_TICBASED), // tic-based logic + (args[4] & TMFT_RELATIVE), // Relative destvalue + !(args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS + !(args[4] & TMFT_DONTDOTRANSLUCENT), // do not handle FOF_TRANSLUCENT + !(args[4] & TMFT_DONTDOLIGHTING), // do not handle lighting + !(args[4] & TMFT_DONTDOCOLORMAP), // do not handle colormap + !(args[4] & TMFT_IGNORECOLLISION), // do not handle collision + (args[4] & TMFT_GHOSTFADE), // do ghost fade (no collision during fade) + (args[4] & TMFT_USEEXACTALPHA)); // use exact alpha values (for opengl) else { // If fading an invisible FOF whose render flags we did not yet set, // initialize its alpha to 1 // for relative alpha calc - if (!(line->args[4] & TMFT_DONTDOTRANSLUCENT) && // do translucent + if (!(args[4] & TMFT_DONTDOTRANSLUCENT) && // do translucent (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE !(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERPLANES) && @@ -3242,16 +3366,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, rover->alpha, - max(1, min(256, (line->args[4] & TMFT_RELATIVE) ? rover->alpha + destvalue : destvalue)), + max(1, min(256, (args[4] & TMFT_RELATIVE) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately false, NULL, // tic-based logic - !(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS - !(line->args[4] & TMFT_DONTDOTRANSLUCENT), // do not handle FOF_TRANSLUCENT - !(line->args[4] & TMFT_DONTDOLIGHTING), // do not handle lighting - !(line->args[4] & TMFT_DONTDOCOLORMAP), // do not handle colormap - !(line->args[4] & TMFT_IGNORECOLLISION), // do not handle collision - (line->args[4] & TMFT_GHOSTFADE), // do ghost fade (no collision during fade) - (line->args[4] & TMFT_USEEXACTALPHA)); // use exact alpha values (for opengl) + !(args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS + !(args[4] & TMFT_DONTDOTRANSLUCENT), // do not handle FOF_TRANSLUCENT + !(args[4] & TMFT_DONTDOLIGHTING), // do not handle lighting + !(args[4] & TMFT_DONTDOCOLORMAP), // do not handle colormap + !(args[4] & TMFT_IGNORECOLLISION), // do not handle collision + (args[4] & TMFT_GHOSTFADE), // do ghost fade (no collision during fade) + (args[4] & TMFT_USEEXACTALPHA)); // use exact alpha values (for opengl) } } j++; @@ -3259,7 +3383,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!foundrover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Special type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } } @@ -3268,8 +3392,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 454: // Stop fading FOF { - INT16 sectag = (INT16)(line->args[0]); - INT16 foftag = (INT16)(line->args[1]); + INT16 sectag = (INT16)(args[0]); + INT16 foftag = (INT16)(args[1]); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message @@ -3280,7 +3404,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (!sec->ffloors) { - CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Target sector #%d has no FOFs.\n", secnum); + CONS_Debug(DBG_GAMELOGIC, "Special type 454 Executor: Target sector #%d has no FOFs.\n", secnum); return; } @@ -3291,13 +3415,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) foundrover = true; P_ResetFakeFloorFader(rover, NULL, - !(line->args[2])); // do not finalize collision flags + !(args[2])); // do not finalize collision flags } } if (!foundrover) { - CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); + CONS_Debug(DBG_GAMELOGIC, "Special type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } } @@ -3307,25 +3431,35 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 455: // Fade colormap { extracolormap_t *dest; - if (!udmf) + + if (backwardsCompat) + { dest = sides[line->sidenum[0]].colormap_data; + } else { - if (!line->args[1]) + if (!args[1]) + { + if (line == NULL) + { + CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Can't find frontsector with destination colormap!\n"); + return; + } dest = line->frontsector->extra_colormap; + } else { - INT32 destsec = Tag_Iterate_Sectors(line->args[1], 0); + INT32 destsec = Tag_Iterate_Sectors(args[1], 0); if (destsec == -1) { - CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", line->args[1]); + CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", args[1]); return; } dest = sectors[destsec].extra_colormap; } } - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { extracolormap_t *source_exc, *dest_exc, *exc; @@ -3333,21 +3467,27 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) continue; // Don't interrupt ongoing fade - if (!(line->args[3] & TMCF_OVERRIDE) + if (!(args[3] & TMCF_OVERRIDE) && sectors[secnum].fadecolormapdata) //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) { - CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); + CONS_Debug(DBG_GAMELOGIC, "Special type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); continue; } - if (!udmf && (line->flags & ML_TFERLINE)) // use back colormap instead of target sector + if (backwardsCompat && (line->flags & ML_TFERLINE)) // use back colormap instead of target sector + { sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? - sides[line->sidenum[1]].colormap_data : NULL; + sides[line->sidenum[1]].colormap_data : NULL; + } + else + { + sectors[secnum].extra_colormap = NULL; + } exc = sectors[secnum].extra_colormap; - if (!(line->args[3] & TMCF_FROMBLACK) // Override fade from default rgba + if (!(args[3] & TMCF_FROMBLACK) // Override fade from default rgba && !R_CheckDefaultColormap(dest, true, false, false) && R_CheckDefaultColormap(exc, true, false, false)) { @@ -3369,22 +3509,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else source_exc = exc ? exc : R_GetDefaultColormap(); - if (line->args[3] & TMCF_RELATIVE) + if (args[3] & TMCF_RELATIVE) { exc = R_AddColormaps( source_exc, dest, - line->args[3] & TMCF_SUBLIGHTR, - line->args[3] & TMCF_SUBLIGHTG, - line->args[3] & TMCF_SUBLIGHTB, - line->args[3] & TMCF_SUBLIGHTA, - line->args[3] & TMCF_SUBFADER, - line->args[3] & TMCF_SUBFADEG, - line->args[3] & TMCF_SUBFADEB, - line->args[3] & TMCF_SUBFADEA, - line->args[3] & TMCF_SUBFADESTART, - line->args[3] & TMCF_SUBFADEEND, - line->args[3] & TMCF_IGNOREFLAGS, + args[3] & TMCF_SUBLIGHTR, + args[3] & TMCF_SUBLIGHTG, + args[3] & TMCF_SUBLIGHTB, + args[3] & TMCF_SUBLIGHTA, + args[3] & TMCF_SUBFADER, + args[3] & TMCF_SUBFADEG, + args[3] & TMCF_SUBFADEB, + args[3] & TMCF_SUBFADEA, + args[3] & TMCF_SUBFADESTART, + args[3] & TMCF_SUBFADEEND, + args[3] & TMCF_IGNOREFLAGS, false); } else @@ -3400,25 +3540,25 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) Z_Free(exc); Add_ColormapFader(§ors[secnum], source_exc, dest_exc, true, // tic-based timing - line->args[2]); + args[2]); } break; } case 456: // Stop fade colormap - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) P_ResetColormapFader(§ors[secnum]); break; case 457: // Track mobj angle to point if (mo) { - INT32 failureangle = FixedAngle((min(max(abs(line->args[1]), 0), 360))*FRACUNIT); - INT32 failuredelay = abs(line->args[2]); - INT32 failureexectag = line->args[3]; - boolean persist = !!(line->args[4]); + INT32 failureangle = FixedAngle((min(max(abs(args[1]), 0), 360))*FRACUNIT); + INT32 failuredelay = abs(args[2]); + INT32 failureexectag = args[3]; + boolean persist = !!(args[4]); mobj_t *anchormo; - anchormo = P_FindObjectTypeFromTag(MT_ANGLEMAN, line->args[0]); + anchormo = P_FindObjectTypeFromTag(MT_ANGLEMAN, args[0]); if (!anchormo) return; @@ -3444,24 +3584,24 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // console player only if (mo && mo->player && P_IsLocalPlayer(mo->player)) { - INT32 promptnum = max(0, line->args[0] - 1); - INT32 pagenum = max(0, line->args[1] - 1); - INT32 postexectag = abs(line->args[3]); + INT32 promptnum = max(0, args[0] - 1); + INT32 pagenum = max(0, args[1] - 1); + INT32 postexectag = abs(args[3]); - boolean closetextprompt = (line->args[2] & TMP_CLOSE); - //boolean allplayers = (line->args[2] & TMP_ALLPLAYERS); - boolean runpostexec = (line->args[2] & TMP_RUNPOSTEXEC); - boolean blockcontrols = !(line->args[2] & TMP_KEEPCONTROLS); - boolean freezerealtime = !(line->args[2] & TMP_KEEPREALTIME); - //boolean freezethinkers = (line->args[2] & TMP_FREEZETHINKERS); - boolean callbynamedtag = (line->args[2] & TMP_CALLBYNAME); + boolean closetextprompt = (args[2] & TMP_CLOSE); + //boolean allplayers = (args[2] & TMP_ALLPLAYERS); + boolean runpostexec = (args[2] & TMP_RUNPOSTEXEC); + boolean blockcontrols = !(args[2] & TMP_KEEPCONTROLS); + boolean freezerealtime = !(args[2] & TMP_KEEPREALTIME); + //boolean freezethinkers = (args[2] & TMP_FREEZETHINKERS); + boolean callbynamedtag = (args[2] & TMP_CALLBYNAME); if (closetextprompt) F_EndTextPrompt(false, false); else { - if (callbynamedtag && line->stringargs[0] && line->stringargs[0][0]) - F_GetPromptPageByNamedTag(line->stringargs[0], &promptnum, &pagenum); + if (callbynamedtag && stringargs[0] && stringargs[0][0]) + F_GetPromptPageByNamedTag(stringargs[0], &promptnum, &pagenum); F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); } } @@ -3469,8 +3609,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 460: // Award rings { - INT16 rings = line->args[0]; - INT32 delay = line->args[1]; + INT16 rings = args[0]; + INT32 delay = args[1]; if (mo && mo->player) { // Don't award rings while SPB is targetting you @@ -3480,7 +3620,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (delay <= 0 || !(leveltime % delay)) { // args[2]: don't cap rings to 20 - K_AwardPlayerRings(mo->player, rings, line->args[2]); + K_AwardPlayerRings(mo->player, rings, args[2]); } } } @@ -3488,32 +3628,32 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 461: // Spawns an object on the map based on texture offsets { - const mobjtype_t type = line->stringargs[0] ? get_number(line->stringargs[0]) : MT_NULL; + const mobjtype_t type = stringargs[0] ? get_number(stringargs[0]) : MT_NULL; mobj_t *mobj; fixed_t x, y, z; - if (line->args[4]) // If args[4] is set, spawn randomly within a range + if (args[4]) // If args[4] is set, spawn randomly within a range { - x = P_RandomRange(PR_UNDEFINED, line->args[0], line->args[5])<args[1], line->args[6])<args[2], line->args[7])<args[0] << FRACBITS; - y = line->args[1] << FRACBITS; - z = line->args[2] << FRACBITS; + x = args[0] << FRACBITS; + y = args[1] << FRACBITS; + z = args[2] << FRACBITS; } mobj = P_SpawnMobj(x, y, z, type); if (mobj) { - mobj->angle = FixedAngle(line->args[3] << FRACBITS); - CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. + mobj->angle = FixedAngle(args[3] << FRACBITS); + CONS_Debug(DBG_GAMELOGIC, "Special Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. } else - CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special); + CONS_Alert(CONS_ERROR,"Special Type %d - Spawn Object: Object did not spawn!\n", special); } break; @@ -3536,7 +3676,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (mo) { - INT32 color = line->stringargs[0] ? get_number(line->stringargs[0]) : SKINCOLOR_NONE; + INT32 color = stringargs[0] ? get_number(stringargs[0]) : SKINCOLOR_NONE; if (color < 0 || color >= numskincolors) return; @@ -3555,7 +3695,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Find the center of the Eggtrap and release all the pretty animals! // The chimps are my friends.. heeheeheheehehee..... - LouisJM - TAG_ITER_THINGS(line->args[0], mtnum) + TAG_ITER_THINGS(args[0], mtnum) { mo2 = mapthings[mtnum].mobj; @@ -3571,7 +3711,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_KillMobj(mo2, NULL, mo, DMG_NORMAL); } - if (!(line->args[1])) + if (!(args[1])) { INT32 i; @@ -3590,22 +3730,22 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { INT32 linenum; - if (!udmf) + if (backwardsCompat) break; - TAG_ITER_LINES(line->args[0], linenum) + TAG_ITER_LINES(args[0], linenum) { - if (line->args[2]) - lines[linenum].executordelay += line->args[1]; + if (args[2]) + lines[linenum].executordelay += args[1]; else - lines[linenum].executordelay = line->args[1]; + lines[linenum].executordelay = args[1]; } } break; case 466: // Set level failure state { - if (line->args[1]) + if (args[1]) { stagefailed = false; CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); @@ -3619,7 +3759,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 467: // Set light level - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { if (sectors[secnum].lightingdata) { @@ -3628,26 +3768,26 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) sectors[secnum].lightingdata = NULL; } - if (line->args[2] == TML_FLOOR) + if (args[2] == TML_FLOOR) { - if (line->args[3]) - sectors[secnum].floorlightlevel += line->args[1]; + if (args[3]) + sectors[secnum].floorlightlevel += args[1]; else - sectors[secnum].floorlightlevel = line->args[1]; + sectors[secnum].floorlightlevel = args[1]; } - else if (line->args[2] == TML_CEILING) + else if (args[2] == TML_CEILING) { - if (line->args[3]) - sectors[secnum].ceilinglightlevel += line->args[1]; + if (args[3]) + sectors[secnum].ceilinglightlevel += args[1]; else - sectors[secnum].ceilinglightlevel = line->args[1]; + sectors[secnum].ceilinglightlevel = args[1]; } else { - if (line->args[3]) - sectors[secnum].lightlevel += line->args[1]; + if (args[3]) + sectors[secnum].lightlevel += args[1]; else - sectors[secnum].lightlevel = line->args[1]; + sectors[secnum].lightlevel = args[1]; sectors[secnum].lightlevel = max(0, min(255, sectors[secnum].lightlevel)); } } @@ -3657,21 +3797,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { INT32 linenum; - if (!udmf) + if (backwardsCompat) break; - if (line->args[1] < 0 || line->args[1] >= NUMLINEARGS) + if (args[1] < 0 || args[1] >= NUMLINEARGS) { - CONS_Debug(DBG_GAMELOGIC, "Linedef type 468: Invalid linedef arg %d\n", line->args[1]); + CONS_Debug(DBG_GAMELOGIC, "Linedef type 468: Invalid linedef arg %d\n", args[1]); break; } - TAG_ITER_LINES(line->args[0], linenum) + TAG_ITER_LINES(args[0], linenum) { - if (line->args[3]) - lines[linenum].args[line->args[1]] += line->args[2]; + if (args[3]) + lines[linenum].args[args[1]] += args[2]; else - lines[linenum].args[line->args[1]] = line->args[2]; + lines[linenum].args[args[1]] = args[2]; } } break; @@ -3680,24 +3820,24 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { fixed_t gravityvalue; - if (!udmf) + if (backwardsCompat) break; - if (!line->stringargs[0]) + if (!stringargs[0]) break; - gravityvalue = FloatToFixed(atof(line->stringargs[0])); + gravityvalue = FloatToFixed(atof(stringargs[0])); - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { - if (line->args[1]) + if (args[1]) sectors[secnum].gravity = FixedMul(sectors[secnum].gravity, gravityvalue); else sectors[secnum].gravity = gravityvalue; - if (line->args[2] == TMF_ADD) + if (args[2] == TMF_ADD) sectors[secnum].flags |= MSF_GRAVITYFLIP; - else if (line->args[2] == TMF_REMOVE) + else if (args[2] == TMF_REMOVE) sectors[secnum].flags &= ~MSF_GRAVITYFLIP; } } @@ -3705,24 +3845,59 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing + if (line == NULL) + { + break; // TODO + } + PolyDoor(line); break; case 482: // Polyobj_Move + if (line == NULL) + { + break; // TODO + } + PolyMove(line); break; case 484: // Polyobj_RotateRight + if (line == NULL) + { + break; // TODO + } + PolyRotate(line); break; case 488: // Polyobj_Waypoint + if (line == NULL) + { + break; // TODO + } + PolyWaypoint(line); break; case 489: + if (line == NULL) + { + break; // TODO + } + PolySetVisibilityTangibility(line); break; case 491: + if (line == NULL) + { + break; // TODO + } + PolyTranslucency(line); break; case 492: + if (line == NULL) + { + break; // TODO + } + PolyFade(line); break; @@ -3738,7 +3913,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } - TAG_ITER_SECTORS(line->args[0], secnum) + TAG_ITER_SECTORS(args[0], secnum) { sec = sectors + secnum; @@ -3746,7 +3921,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (thing->type == MT_WAYPOINT) { - if (line->flags & ML_NOCLIMB) + if (args[1]) { thing->extravalue1 = 1; }