diff --git a/SRC/DEV_DOCS/List_of_Func_and_Const.md b/SRC/DEV_DOCS/MM_Func&Const_List.md similarity index 85% rename from SRC/DEV_DOCS/List_of_Func_and_Const.md rename to SRC/DEV_DOCS/MM_Func&Const_List.md index e996412..ff49adb 100644 --- a/SRC/DEV_DOCS/List_of_Func_and_Const.md +++ b/SRC/DEV_DOCS/MM_Func&Const_List.md @@ -1,8 +1,4 @@ -## List of functions and constants - -### For LTM's Murder Mystery `1.0-ALPHA` - ---- +# List of functions and constants for LTM's Murder Mystery `1.0-ALPHA` This document contains the description of some important and globaly defined functions as well as constants which are used in Murder Mystery's LUA source code. @@ -23,15 +19,14 @@ This document contains the description of some important and globaly defined fun - Win reasons (`WIN_*`) - Time Zones (`TIMEZONE_*`) - Time Warp (`TWS_*`) -- [The core `MM` table](#the-core-mm-table) -# Functions +## Functions ## `INIT.LUA` ### Customisation API -There is a customization function defined in MM table inside the code which allows you to create your own "sub-mods" for the Murder Mystery gametype. +There is a customization function defined in the [MM](./MM_Userdata_Structure.md#the-core-mm-table) table inside the code which allows you to create your own "sub-mods" for the Murder Mystery gametype. | Name | Description | | --- | --- | @@ -60,7 +55,7 @@ These are the functions that are used in [`GAME.LUA`](../LUA/MAIN//GAME.LUA) (th | **MM_StartSuspenceMusic**() | *boolean* | Starts the Suspence music and returns `true` if there are no Sheriffs and no Heroes alive but one Innocent with at least one Sheriff's Emerald dropped. | | **MM_StartShowdownMusic**() | *boolean* | Starts one of the Showdown Duel tunes and returns `true` if there are no Innocents in the game.| | **MM_SetRandomInnoAs**(*int* role, *int* message) | nil | Similar to **MM_AssignRoles()** but works for only for Innocents. In some gameplay situations, there has to be a replacement of the player with some important role and this function selects random Innocent to give the role to it. Any of the `ROLE_*` constants (except `ROLE_INNOCENT`) can act as a possible value for the role argument.
Possible values for Message:
ValueMessage
1*"You became a Murderer"*
2*"You became a Sheriff"*
3*"You became a Hero"*
4*"You were rewarded the role of Hero"*
| -| **MM_GetMMSHREMLinterval**(*int* distance) | *int* | Get the interval time in tics between each radar beep depending on the dist distance. Used for Innocents' Sheriff Emerald radar. | +| **MM_GetMMSHREMDinterval**(*int* distance) | *int* | Get the interval time in tics between each radar beep depending on the dist distance. Used for Innocents' Sheriff Emerald radar. | | **MM_IsTimelineCorrect**(*int* timezone1, *int* timezone2) | *boolean* | Check if the events from timezone1 can happen in timezone2. For example, if the event has happened in the *Past* the consequence of this event can be seen in the *Present*, *Bad Future*, and *Good Future*. But the event from the *Present*, *Bad Future*, or the *Good Future* cannot be seen in the *Past* (because it happened in the future). For easier understanding imagine a one-way road (timeline): `Past > Present > Bad/Good Future`
*Note:* Both of the arguments are `TIMEZONE_*` constants. | | **MM_GetText**(*string* language, *string* line, [*string*/*int* parameter]) | *string* | A safe way to extract the strings from the global MM Text Table (MM.text) without crashing/erroring LUA. When all 3 arguments are given this function returns the value at MM.text[language][line][parameter]. If only language and line arguments are given the function returns the value from MM.text[language][line]. If the text is not found or the arguments are invalid a blank string is returned instead.
*Note:* Even if the expected return value is table, this function will return an empty string!
*In Debug Builds:* If the text can not be reached or invalid arguments are given an error is triggered with the details. | | **MM_PunishPlayer**(*player_t* player, *string* message, [*boolean* ban?]) | *nil* | Kick player from the game or ban if ban? is set. message is the kick/ban message.
*Note:* If the player who is going to be punished is the host, SRB2 automatically closes for this player, causing the server to shut down. | @@ -104,7 +99,7 @@ Functions that are used in more than one script | --- | --- | --- | | **PlayerCount**([*int* role]) | *int* | Get the total number of players online. If the role is specified return the total number of players who have the role. | | **PlayersAlive**() | *int* | Get the number of players who are still alive (aren't spectators). | -| **MM_SpawnSHREML**(*int* x, *int* y, *int* z, [*int* timezone]) | nil | Spawn the Sheriff's Emerald at (x, y, z) position. timezone argument is optional and is used only go get the timezone the Emerald was spawned in. | +| **MM_SpawnSHREMD**(*int* x, *int* y, *int* z, [*int* timezone]) | nil | Spawn the Sheriff's Emerald at (x, y, z) position. timezone argument is optional and is used only go get the timezone the Emerald was spawned in. | | **P_GetSectorCeilingZAt**(*sector_t* sector, *int* x, *int* y) | *fixed_t* | Returns the height of the sector ceiling at (x, y), works both for regular sectors and slopes. Ported from SRB2 source code | | **P_GetFOFTopZAt**(*ffloor_t* fof, *int* x, *int* y) | *fixed_t* | Returns the top height of the FOF at (x, y). Ported from SRB2 source code | | **P_GetFOFBottomZAt**(*ffloor_t* fof, *int* x, *int* y) | *fixed_t* | Returns the bottom height of the FOF at (x, y). Ported from SRB2 source code | @@ -183,25 +178,4 @@ The constants for the configurations flag checks. Useful only with the `mm_wepco | `WEPCFG_REDONLY` | 1 | Only the Weapon Slot 1 is usable (Red/Infinite rings. Knife) | `WEPCFG_DISABLERED` | 2 | Weapon Slot 1 is occupied by the Knife only | -# The core `MM` table - -The description of each value in the `MM` table. The `MM` constant itself is defined in [INIT.LUA](../INIT.LUA) - -| Name | Type | Description | Example value | -| --- | --- | --- | --- | -| version | *string* | Version number of the add-on | "1.0-ALPHA" | -| debug | *boolean* | Enable/Disable the add-on's *Debug Mode* functionality
*Note:* **The add-on must boot with this variable set to true to use the Debug in any form.** | true | -| releasedate | *string* | The release date of the add-on version. | "August 19th 2024" | -| text | *table* | Collection of all text used in **Murder Mystery** with all translations. This variable is **netsynced** | *See [the template file](../LUA/TEXT/EN.LUA)* | -| RoleColor | *string[5]* | The text colors for roles | *See [INIT.LUA](../INIT.LUA)* | -| RoleColorHUD | *string[5]* | The HUD text colors for roles | *See [INIT.LUA](../INIT.LUA)* | -| hud | *table* | HUD control variables for each sub-renderer (MM.hud.game, MM.hud.scores, MM.hud.intermission). Each sub-renderer has two attributes: enabled (custom scripts can disable MM's HUD renderers by setting this to false) and pos (coordinates of the different HUD elements) | *See [INIT.LUA](../INIT.LUA)* | -| weaponconfig | *int[4]* | Table to contain the Weapon Configurations. Updated by the `mm_wepconfig` CVAR. | *See [MM_WEPCONFIG.PNG](MM_WEPCONFIG.PNG) and [INIT.LUA](../INIT.LUA)* | -| shwdwn | *string* | The 6-character name of the current Showdown Duel track playing, also marks if the Duel is happening right now or not | "S2MSBS" | -| winner | *int* | The winner of the round, can be one of the 3 possible values: *0* - Tie, *1* - Murderer, *2* - Civilians (Sheriffs, Heros and Innocents). This variable is **netsynced** | 0 | -| winreason | *int* | The win reason, can be one of the WIN_* constants. This variable is **netsynced** | 1 | -| timelimit | *int* | Works just like SRB2's vanilla `timelimit` but MM uses its own. The value is measured in Minutes. This variable is **netsynced** | 5 | -| shremls | *mobj_t[]* | The table containing all dropped *Sheriff Emerald* objects | *See [LUA/GAME.LUA](../LUA/GAME.LUA)* | -| pong | *table* | Variables for Pong 2-player minigame. This variable is **netsynced** | *See [INIT.LUA](../INIT.LUA) and [LUA/MINIGAMES/MINIGAMES.LUA](../LUA/MINIGAMES/MINIGAMES.LUA)* | - # That's all folks! diff --git a/SRC/DEV_DOCS/MM_Userdata_Structure.md b/SRC/DEV_DOCS/MM_Userdata_Structure.md new file mode 100644 index 0000000..82e10e4 --- /dev/null +++ b/SRC/DEV_DOCS/MM_Userdata_Structure.md @@ -0,0 +1,62 @@ +# MM Userdata structure for LTM's Murder Mystery `1.0-ALPHA` + +This document describes the structure of the MM data + +## Table of contents +- [player_t.mm](#player_tmm) +- [MT_SHREMD](#mt_shremd) +- [Global MM table](#the-core-mm-table) + +### player_t.mm + +MM userdata related to the player. In the examples below, p is used as the name of the player_t variable. **An access to the MM-related variable var of player_t is written as p.mm.var**. + +| Name | Type | Description | +| --- | --- | --- | +| **role** | *int*, one of the ROLE_* constants | Specifies the player's current role in the game. See the [documentation](./MM_Func&Const_List.md#constants) for the details on the constants for this variable. | +| **kills** | *int* | The number of kills the player has made. In **PONG** 2-player minigame this variable acts as the score per-player. | +| **killername** | *string* | The name of the player who killed player p.
***Note:*** The code has a special exception for the killer player's name set as `"your stupidity"` as it sometimes is used to identify the players who died by the map hazard (crusher, pit, drowned in water, etc.). This name will be also translated on HUD. | +| **lang** | *string* | The player's currently set language. Translates all the game messages and HUD-related text into the specified language. For example, p.mm.lang = "EN" will set the player's language to English. | +| **weapondelay** | *tic_t* | It is very similar to the p.weapondelay, but this one (p.mm.weapondelay) is used for the MM recreation of the weapons since the vanilla variable is always set to 0 to prevent the vanilla weapons from firing. | +| **sneak** | *boolean* | This variable tells whether or not the player is currently sneaking. While sneaking, the player makes no footstep sounds and leaves no footmarks on the ground. | +| **afk** | *tic_t* | The player's AFK timer. Depending on the value of the `mm_afk` Console Variable, it is used to calculate and kick the innactive players. | +| **camping** | *tic_t* | "Camping timer" for players with the **Murderer** role. Depending on the value of the `mm_camping` Console Variable, it is used to kick players with p.mm.role == ROLE_MURDERER who are sitting near the dropped *Sheriff's Emerald* for longer than 30 seconds. | +| **chatdelay** | *tic_t* | The player's delay timer which controls the time interval the player must wait before sending another message. | +| **shremd_dist** | *fixed_t* | The distance to the closest dropped *Sheriff's Emerald*. It is calcualted only for the **Murderers** (for calculating p.mm.camping) and **Innocents**. (for Emerald Radar). | +| **hud** | *userdata table* | The table with the player's HUD related data:
NameTypeDescription
**fx_translucency***int*The translucency of the fullscreen flash/spark effect. The effect is inactive when the value is set to 0 or >=10.
**fx_duration***int*The duration of the effect's frame. It should be noted that the formula for calculating the progression of the effect frame looks like
if (not (leveltime & p.mm.fx_duration)) then p.mm.fx_translucency = $ + 1 end
which means the p.mm.fx_duration can only represent the amount of frames as `(2^n) - 1`.
**fx_color***int*The SRB2's pallet color used for the effect.
**roleflicker***tic_t*The amount of time (in tics) the role label on HUD should flicker.
| +| **timetravel** | *userdata table* | The table with the player's Time Travel related data:
NameTypeDescription
**timezone***int*, one of the TIMEZONE_** constantsThe time zone the player is currently in. For maps that do not utilize the time travel mechanic the value of this variable will always be TIMEZONE_PRESENT. See [the documentation](./MM_Func&Const_List.md#constants) for the details on the constants for this variable.
**timesign***int*, one of the TWS_** constantsThe time warp sign (Past/Future sign) the player is currently holding. This variable is set back to TWS_NONE when the player succesfully warps into another time zone or has failed to keep enough speed for the warp. See [the documentation](./MM_Func&Const_List.md#constants) for the details on the constants for this variable.
**warptimer***tic_t*The amount of time (in tics) player is in the warping state.
| +| **help** | *userdata table* | The table with the player's GUI manual related data:
NameTypeDescription
**active***boolean*Tells whether or not the help manual is activated at the moment. It can be activated by the player by activating the `mmhelp` Console Command.
**page***int*The number of the manual page the player is currently looking at.
**pos***int*The current possition on the page.
| + +### MT_SHREMD +The userdata of the dropped Sheriff Emerald's object (MT_SHREMD) + +| Name | Type | Description | +| --- | --- | --- | +| **x** | *fixed_t* | The Emerald's X possition | +| **y** | *fixed_t* | The Emerald's Y possition | +| **z** | *fixed_t* | The Emerald's Z possition | +| **timezone** | *int*, one of the TIMEZONE_* constants | The timezone the emerald is dropped in | + +### The core `MM` table + +The description of each value in the `MM` table. The `MM` constant itself is defined in [INIT.LUA](../INIT.LUA) + +| Name | Type | Description | +| --- | --- | --- | +| **version** | *string* | Version number of the add-on. | +| **debug** | *boolean* | Enable/Disable the add-on's *Debug Mode* functionality
*Note:* **The add-on must boot with this variable set to true to use the Debug in any form.** | +| **builddate** | *string* | The build date of the add-on. | +| **text** | *table* | Collection of all text used in **Murder Mystery** with all translations. This variable is **netsynced**. See the [source code](../LUA/) for details. | +| **RoleColor** | *string[5]* | The vanilla text colors for roles, use one of the ROLE_* constants as index to get the color for the specified role. For the dead player color access MM.RoleColor[5].| +| **RoleColorHUD** | *string[5]* | The MM text colors for roles, use one of the ROLE_* constants as index to get the color for the specified role. For the dead player color access MM.RoleColorHUD[5]. | +| **hud** | *table* | HUD control variables for each sub-renderer (MM.hud.game, MM.hud.scores, MM.hud.intermission). Each sub-renderer has two attributes: **enabled** (custom scripts can disable MM's HUD renderers by setting this to false) and pos (coordinates of the different HUD elements). | +| **weaponconfig** | *int[4]* | Table to contain the Weapon Configurations. Updated by the `mm_wepconfig` CVAR. See [MM_WEPCONFIG.PNG](MM_WEPCONFIG.PNG) and [INIT.LUA](../INIT.LUA) for details. | +| **shwdwn** | *string* | The 6-character name of the current Showdown Duel track playing, also marks if the Duel is happening right now or not | "S2MSBS" | +| **winner** | *int* | The winner of the round, can be one of the 3 possible values: *0* - Tie, *1* - Murderer, *2* - Civilians (Sheriffs, Heros and Innocents). This variable is **netsynced**. | +| **winreason** | *int* | The win reason, can be one of the WIN_* constants. This variable is **netsynced**. | +| **timelimit** | *int* | Works just like SRB2's vanilla `timelimit` but MM uses its own. The value is measured in Minutes. This variable is **netsynced**. | +| **shremds** | *mobj_t[]* | The table containing all dropped *Sheriff Emerald* objects (MT_SHREMD). | +| **pong** | *table* | Variables for Pong 2-player minigame. This variable is **netsynced**. See [INIT.LUA](../INIT.LUA) and [LUA/MINIGAMES/MINIGAMES.LUA](../LUA/MINIGAMES/MINIGAMES.LUA) for details. | +| **MM.AddLang**(*string* index, *table* lang) | *function* | Add a translation into MM. index is usually a 2 or 3 characters long name of the language. For example `"EN"` shows that the language is English. table is the translation data itself. The format of the table can be found [here](../LUA/TEXT/EN.LUA).
*Note:* Index should be all characters **UPPERCASE** otherwise it won't be accesible! | + +# That's all folks! diff --git a/SRC/FOR_DEVELOPERS.TXT b/SRC/FOR_DEVELOPERS.TXT index 4336185..dc1d04a 100644 --- a/SRC/FOR_DEVELOPERS.TXT +++ b/SRC/FOR_DEVELOPERS.TXT @@ -11,8 +11,10 @@ MM_LTMs_MurderMystery_v1.0-ALPHA.pk3 +-INIT.LUA - Init, freeslot, add-on PK3 properties, and some objects | +-DEV_DOCS-\ -| +-List_of_Func_and_Const.md - Documentation of functions and constants -| \-MM_HUD_Library.md - Documentation of the "Murder Mystery HUD library" +| +-MM_Func&Const_List.md - Documentation of functions and constants +| +-MM_HUD_Library.md - Documentation of the "Murder Mystery HUD library" +| +-MM_Userdata_Structure.md - Documentation of the various MM userdata tables +| \-MM_WEPCONFIG.PNG - Visual explanation of the CVAR of the same name (in binary form) | +-LUA-\ | | @@ -28,7 +30,7 @@ MM_LTMs_MurderMystery_v1.0-ALPHA.pk3 | | +-MINIGAME.LUA - Main logic code for "PONG" and "SONIC RUN" minigames | | | +-TEXT-\ -| | +-EN.LUA - All Text and messages used in the add-on (English version), also a template file for other languages +| | \-EN.LUA - All Text and messages used in the add-on (English version), also a template file for other languages | | | +-ABILITIES.LUA - Character abilities & sneak | +-CCMD.LUA - MMHELP and MMLANG commands diff --git a/SRC/INIT.LUA b/SRC/INIT.LUA index a9356d4..5f5b3c5 100644 --- a/SRC/INIT.LUA +++ b/SRC/INIT.LUA @@ -5,7 +5,7 @@ end rawset(_G, "MM", { version = "1.0-ALPHA", --string, VERSION NUMBER debug = true, --boolean, if set to true, enable the debug functionality in MM - releasedate = "not released yet", --string, meant to contain the day of release + builddate = "N/A", --string, meant to contain the day of the build RoleColor = { "\x85", --Murderer "\x84", --Sheriff @@ -60,7 +60,7 @@ rawset(_G, "MM", { winner = 0, --for intermission, netsynced winreason = 0, --for intermission, netsynced timelimit = 5, --for custom timelimit, netsynced - shremls = {}, --table containing all dropped Sheriff Emeralds mobj_t values, netsynced + shremds = {}, --table containing all dropped Sheriff Emeralds mobj_t values, netsynced pong = { --some of the variables for Pong minigame, netsynced ball = {x=80, y=40}, velocity = {x=0, y=0}, @@ -149,15 +149,15 @@ local function VarChange(v) --callback function called by CV_CALL flag end end -- Flags: 4 = CV_NETVAR; 6 = CV_NETVAR|CV_CALL -CV_RegisterVar({name = "mm_abilities", defaultvalue = "Off", PossibleValue = CV_OnOff, flags = 6, func = VarChange}) -CV_RegisterVar({name = "mm_afk", defaultvalue = 2, PossibleValue = {MIN = 0, MAX = 10}, flags = 4}) -CV_RegisterVar({name = "mm_autofire", defaultvalue = "On", PossibleValue = CV_OnOff, flags = 4}) -CV_RegisterVar({name = "mm_chatdelay", defaultvalue = 1, PossibleValue = {MIN = 0, MAX = 60}, flags = 4}) -CV_RegisterVar({name = "mm_cryptic", defaultvalue = "Off", PossibleValue = CV_OnOff, flags = 6, func = VarChange}) -CV_RegisterVar({name = "mm_customskins", defaultvalue = "No", PossibleValue = CV_YesNo, flags = 4}) -CV_RegisterVar({name = "mm_nocamping", defaultvalue = "On", PossibleValue = CV_OnOff, flags = 4}) -CV_RegisterVar({name = "mm_wepconfig", defaultvalue = 1, PossibleValue = {MIN = 0, MAX = 255}, flags = 6, func = VarChange}) CV_RegisterVar({name = "mm_wepinno", defaultvalue = 1, PossibleValue = {MIN = 0, MAX = 2}, flags = 6, func = VarChange}) +CV_RegisterVar({name = "mm_wepconfig", defaultvalue = 1, PossibleValue = {MIN = 0, MAX = 255}, flags = 6, func = VarChange}) +CV_RegisterVar({name = "mm_nocamping", defaultvalue = "On", PossibleValue = CV_OnOff, flags = 4}) +CV_RegisterVar({name = "mm_customskins", defaultvalue = "No", PossibleValue = CV_YesNo, flags = 4}) +CV_RegisterVar({name = "mm_cryptic", defaultvalue = "Off", PossibleValue = CV_OnOff, flags = 6, func = VarChange}) +CV_RegisterVar({name = "mm_chatdelay", defaultvalue = 1, PossibleValue = {MIN = 0, MAX = 60}, flags = 4}) +CV_RegisterVar({name = "mm_autofire", defaultvalue = "On", PossibleValue = CV_OnOff, flags = 4}) +CV_RegisterVar({name = "mm_afk", defaultvalue = 2, PossibleValue = {MIN = 0, MAX = 10}, flags = 4}) +CV_RegisterVar({name = "mm_abilities", defaultvalue = "Off", PossibleValue = CV_OnOff, flags = 6, func = VarChange}) -- --MM startup init @@ -165,6 +165,7 @@ CV_RegisterVar({name = "mm_wepinno", defaultvalue = 1, PossibleValue = {MIN = 0, print("\n\x87LTM's MURDER MYSTERY \x81v"..MM.version.."\n") --Freeslot Gametype, Sheriff's Emerald & Knife object +freeslot('TOL_LTM_MM', 'MT_SHREMD', 'MT_MMKNIFE', 'SPR_STEPA0', 'S_MMSTEP', 'MT_MMSTEP') G_AddGametype({ name = "LTM_MM", identifier = "LTMMURDERMYSTERY", @@ -175,11 +176,10 @@ G_AddGametype({ headerrightcolor = 153, description = "\x88LeonardoTheMutant's\x80 \x87Murder Mystery\x80:\nKill everyone as \x85Murderer\x80, prevent the murders as \x84Sheriff\x80 and survive as \x83Innocent\x80!" }) -freeslot('TOL_LTM_MM', 'MT_SHREML', 'MT_MMKNIFE', 'SPR_STEPA0', 'S_MMSTEP', 'MT_MMSTEP') freeslot('sfx_mmdth1', 'sfx_mmdth2', 'sfx_mmdth3', 'sfx_mmdth4', 'sfx_mmdth5', 'sfx_mmdth6', 'sfx_mmdth7') --Sheriff Drop Emerald -mobjinfo[MT_SHREML]={ +mobjinfo[MT_SHREMD]={ spawnstate = S_CEMG3, deathstate = S_SPRK1, deathsound = sfx_cgot, @@ -264,7 +264,7 @@ print("\n\x84LTM's Murder Mystery add-on was loaded succesfuly\n\x82Thank you fo addHook("NetVars", function(net) MM.text = net($) - MM.shremls = net($) + MM.shremds = net($) MM.winner = net($) MM.winreason = net($) MM.timelimit = net($) diff --git a/SRC/LUA/CCMD.LUA b/SRC/LUA/CCMD.LUA index 2dcd8a8..10d3216 100644 --- a/SRC/LUA/CCMD.LUA +++ b/SRC/LUA/CCMD.LUA @@ -6,7 +6,7 @@ local tech_info = { "\4LTM's \7Murder Mystery\16", - "Version\17 "..MM.version.."\16 ("..MM.releasedate..")", + "Version\17 "..MM.version.."\16 ("..MM.builddate..")", "by \18\"SRB2MM_DEV team\"\16", "(Full credits are in README.TXT inside this .PK3)", "\nChanges from\17 10.1-BETA\16:", @@ -29,7 +29,7 @@ COM_AddCommand("mmhelp", function(p, page) CONS_Printf(p, "\x87MM_ABILITIES\x80 - Switch between \x81\"Mystery\"\x80 and \x81\"Vanilla\"\x80 skin abilities mode. Default is \"Mystery\" (OFF).") CONS_Printf(p, "\x87MM_AFK\x80 - AFK timeout in minutes. If player is AFK for the specified amount of minutes it is going to be kicked.") CONS_Printf(p, "\x87MM_AUTOFIRE\x80 - Turn weapon autofire ON/OFF.") - CONS_Printf(p, "\x87MM_CHATDELAY\x80 - The message delay (in ticks) to control the time interval players must wait before sending another message.") + CONS_Printf(p, "\x87MM_CHATDELAY\x80 - The message delay (in tics) to control the time interval players must wait before sending another message.") CONS_Printf(p, "\x87MM_CRYPTIC\x80 - Make the game more cryptic by disabling the teammate list, player nametags and most of the player counters on HUD") CONS_Printf(p, "\x87MM_CUSTOMSKINS\x80 - Allow the usage of the Custom Skins/Characters in MM.") CONS_Printf(p, "\x87MM_NOCAMPING\x80 - When enabled, \x85Murderers\x80 who are camping on the \x84Sheriff's Emerald\x80 for longer than 30 seconds will be kicked") @@ -41,7 +41,7 @@ COM_AddCommand("mmhelp", function(p, page) CONS_Printf(p, "\x82".."DEVELOPER DEBUG COMMANDS") CONS_Printf(p, "\x87MMPLAYER\x80 - Change player state/role") CONS_Printf(p, "\x87MMEXITLEVEL\x80 - Force round end with the winner") - CONS_Printf(p, "\x87MMSHREML\x80 - Spawn Sheriff's Emerald at player's position") + CONS_Printf(p, "\x87MMSHREMD\x80 - Spawn Sheriff's Emerald at player's position") CONS_Printf(p, "\x87MMTIMEWARP\x80 - Travel between different time zones (if map supports them)") CONS_Printf(p, "\x87MMDUEL\x80 - Start the Showdown Duel music") CONS_Printf(p, "\x87MMCHARSET\x80 - Display all Extended ASCII characters from specified character set") diff --git a/SRC/LUA/DEBUG.LUA b/SRC/LUA/DEBUG.LUA index a2e6be9..7460126 100644 --- a/SRC/LUA/DEBUG.LUA +++ b/SRC/LUA/DEBUG.LUA @@ -30,8 +30,8 @@ COM_AddCommand("mmexitlevel",function(p,winner,reason) --exitlevel alternative if (not reason) MM_EndRound(winner,"WIN",winner) else MM_EndRound(winner,"WIN",reason) end end) -COM_AddCommand("mmshreml",function(p) --Spawn Sheriff's Emerald at player's position - MM_SpawnSHREML(p.realmo.x,p.realmo.y,p.realmo.z,p.mm.timetravel.timezone) +COM_AddCommand("mmshremd",function(p) --Spawn Sheriff's Emerald at player's position + MM_SpawnSHREMD(p.realmo.x,p.realmo.y,p.realmo.z,p.mm.timetravel.timezone) end) COM_AddCommand("mmtimewarp",function(p,direction,shift) --Warp between different time zones manually if (gamestate!=1) or (not valid(p.mo)) return end diff --git a/SRC/LUA/FUNCTIONS.LUA b/SRC/LUA/FUNCTIONS.LUA index d53e08d..143493b 100644 --- a/SRC/LUA/FUNCTIONS.LUA +++ b/SRC/LUA/FUNCTIONS.LUA @@ -56,21 +56,22 @@ rawset(_G, "MM_InitPlayer", function(p) if (not p.mm) then p.mm = {} end p.mm.kills = 0 - p.mm.killedby = false + p.mm.killername = false p.mm.weapondelay = 0 p.mm.camping = 0 p.mm.chatdelay = 0 - p.mm.shreml_dist = 0 + p.mm.shremd_dist = 0 p.mm.sneak = false p.mm.hud = { - flashscrn = 0, + fx_translucency = 0, + fx_duration = 0, + fx_color = 0, roleflicker = 140, } p.mm.timetravel = { timezone = TIMEZONE_PRESENT, timesign = TWS_NONE, - warptimer = 0, - spark = 0 + warptimer = 0 } end) @@ -144,7 +145,7 @@ rawset(_G, "MM_AssignRoles", function() for p in players.iterate if (p.mm.role == ROLE_NONE) p.mm.role = ROLE_INNOCENT end --we previously didn't make Innos so make them now chatprintf(p, MM_GetText(p.mm.lang, "ROLE_GET", p.mm.role)) - p.mm.roleflicker = 105 --timer for role name flickering on HUD + p.mm.hud.roleflicker = 105 --timer for role name flickering on HUD end end) @@ -218,10 +219,10 @@ rawset(_G, "MM_KillPlayerByPlayer", function(p, k) --player, killer (both MOBJ_T local plr = p.player plr.spectator = true plr.mm.role = ROLE_NONE - plr.mm.hud.flashscrn = 1 + MM_StartFlashFX(plr, 3, 0x23) --Red flash effect P_PlayerRingBurst(plr, -1) P_PlayerWeaponPanelOrAmmoBurst(plr) - plr.mm.killedby = k.player.name + plr.mm.killername = k.player.name k.player.mm.kills = $ + 1 if (not k.player.mm.sneak) P_PlayDeathSound(p) end plr.rmomx = 0 @@ -248,8 +249,8 @@ rawset(_G, "MM_KillPlayerByHazard", function(p, spawnbody) --player (mobt_t), "S local plr = p.player plr.spectator = true plr.mm.role = ROLE_NONE - plr.mm.hud.flashscrn = 1 - plr.mm.killedby = "your stupidity" + MM_StartFlashFX(plr, 3, 0x23) --Red flash effect + plr.mm.killername = "your stupidity" if (spawnbody) local body = P_SpawnMobjFromMobj(p,0,0,0,MT_DEADPLR) @@ -349,6 +350,21 @@ rawset(_G, "MM_PlayerQuit", function(p) MM_StartShowdownMusic() end) +rawset(_G, "MM_StartFlashFX", function(p, duration, color) + assert(p, "MM_StartFlashFX argument #1: player_t not given!") + assert(p.mm, "MM_StartFlashFX argument #1: player_t.mm table is not initialized!") + assert(p.mm.hud, "MM_StartFlashFX argument #1: player_t.mm.hud table is not initialized!") + assert(duration, "MM_StartFlashFX argument #2: Effect duration time is not specified") + if (type(duration) != "number") then error("MM_StartFlashFX argument #2: The value of the effect duration must be a number") end + if (color and (type(color) != "number")) then error("MM_StartFlashFX argument #3: The value of the effect's color must be a number") end + + color = color or 0 + + p.mm.hud.fx_translucency = 1 + p.mm.hud.fx_duration = duration + p.mm.hud.fx_color = color +end) + --Function to end the round, arguments here: --possible values for the winner of the game are 0-None (Tie), 1-Murderer, 2-Civilians (Sheriff, Innocent, Hero) --endtext is the text to display in the chat (taken from the MM.text) @@ -367,7 +383,7 @@ end) --Enable Suspence music when there are no Sheriffs & Heroes left but one Innocent and at least one dropped Sheriff's Emerald rawset(_G, "MM_StartSuspenceMusic", function() - if ((not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO) and (PlayerCount(ROLE_INNOCENT) == 1) and #MM.shremls)) + if ((not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO) and (PlayerCount(ROLE_INNOCENT) == 1) and #MM.shremds)) S_ChangeMusic("SUSNCE", true) return true end @@ -395,7 +411,7 @@ rawset(_G, "MM_SetRandomInnoAs", function(role, message) end local p = players[plrs[P_RandomKey(#plrs)+1]] p.mm.role = role - p.mm.roleflicker = 70 + p.mm.hud.roleflicker = 70 chatprintf(p, MM_GetText(p.mm.lang, "NEWROLE_GET", message)) return end) @@ -793,11 +809,11 @@ end) -- --spawn Sheriff Emerald -rawset(_G, "MM_SpawnSHREML", function(x, y, z, timezone) - if (x == nil) or (y == nil) or (z == nil) error("Not enough arguments for MM_SpawnSHREML(int x, int y, int z, [player_t player])") end - local mo = P_SpawnMobj(x ,y, z, MT_SHREML) +rawset(_G, "MM_SpawnSHREMD", function(x, y, z, timezone) + if (x == nil) or (y == nil) or (z == nil) error("Not enough arguments for MM_SpawnSHREMD(int x, int y, int z, [player_t player])") end + local mo = P_SpawnMobj(x ,y, z, MT_SHREMD) if (timezone) mo.timezone = timezone end - table.insert(MM.shremls, (#MM.shremls + 1), mo) + table.insert(MM.shremds, (#MM.shremds + 1), mo) end) -- Returns the height of the sector floor at (x, y) diff --git a/SRC/LUA/GAME.LUA b/SRC/LUA/GAME.LUA index c774511..349193a 100644 --- a/SRC/LUA/GAME.LUA +++ b/SRC/LUA/GAME.LUA @@ -9,10 +9,10 @@ local afkCVAR = CV_FindVar("mm_afk") local rejointimeoutCVAR = CV_FindVar("rejointimeout") local crypticCVAR = CV_FindVar("mm_cryptic") -local shreml_distances = {} -local shreml_interval, shreml_closest +local shremd_distances = {} +local shremd_interval, shremd_closest -local function MM_GetSHREMLinterval(dist) +local function MM_GetSHREMDinterval(dist) if (dist < 256) return 5 elseif (dist < 512) return 10 elseif (dist < 1024) return 20 @@ -32,7 +32,7 @@ addHook("MapLoad", function(map) --Prepare the game MM.winner = 0 MM.winreason = 0 - MM.shremls = {} + MM.shremds = {} MM.shwdwn = false --Time limit @@ -146,7 +146,7 @@ addHook("MobjDeath", function(v, i, a, d) --Victim, inflictor (unused here), att if (PlayerCount(ROLE_INNOCENT)) if (spawnBodyOrEmerald) - MM_SpawnSHREML(v.x, v.y, v.z, vp.mm.timetravel.timezone) + MM_SpawnSHREMD(v.x, v.y, v.z, vp.mm.timetravel.timezone) MM_ChatprintGlobal("SHERI_DIED_DROP", vp.name) if (isdedicatedserver) then CONS_Printf(server, "- "..vp.name.." (Sheriff) has died in an accident, dropped his emerald") end else @@ -195,7 +195,7 @@ addHook("MobjDeath", function(v, i, a, d) --Victim, inflictor (unused here), att MM_KillPlayerByHazard(a, true) if (not PlayerCount(ROLE_INNOCENT)) and (not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO)) MM_EndRound(ROLE_MURDERER, "WIN", WIN_HEROKILLINNO) - elseif (PlayerCount(ROLE_INNOCENT)) and (not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO)) and (not #MM.shremls) + elseif (PlayerCount(ROLE_INNOCENT)) and (not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO)) and (not #MM.shremds) MM_EndRound(ROLE_MURDERER, "WIN", WIN_NODEFENDERS) else chatprintf(ap, MM_GetText(ap.mm.lang, "KILL_PUNISHMENT_PM", 2)) @@ -257,7 +257,7 @@ addHook("MobjDamage", function(v, i, a, d) --Victim, inflictor (unused here), at end if (PlayerCount(ROLE_INNOCENT)) - MM_SpawnSHREML(v.x, v.y, v.z, vp.mm.timetravel.timezone) + MM_SpawnSHREMD(v.x, v.y, v.z, vp.mm.timetravel.timezone) MM_ChatprintGlobal("SHERI_KILLED_DROP", vp.name) if (isdedicatedserver) then CONS_Printf(server, "- "..vp.name.." (Sheriff) killed, dropped his emerald") end elseif (not PlayerCount(ROLE_INNOCENT)) and (PlayerCount(ROLE_SHERIFF) or PlayerCount(ROLE_HERO)) @@ -306,7 +306,7 @@ addHook("MobjDamage", function(v, i, a, d) --Victim, inflictor (unused here), at MM_KillPlayerByHazard(a, true) if (not PlayerCount(ROLE_INNOCENT)) and (not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO)) MM_EndRound(ROLE_MURDERER, "WIN", WIN_HEROKILLINNO) - elseif (PlayerCount(ROLE_INNOCENT)) and (not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO)) and (not #MM.shremls) + elseif (PlayerCount(ROLE_INNOCENT)) and (not PlayerCount(ROLE_SHERIFF)) and (not PlayerCount(ROLE_HERO)) and (not #MM.shremds) MM_EndRound(ROLE_MURDERER, "WIN", WIN_NODEFENDERS) else chatprintf(ap, MM_GetText(ap.mm.lang, "KILL_PUNISHMENT_PM", 2)) @@ -335,9 +335,9 @@ addHook("TouchSpecial", function(special, toucher) if (gametype != GT_LTMMURDERMYSTERY) return end if (toucher) and valid(toucher.player) and (toucher.player.mm.role == ROLE_INNOCENT) - for emeraldID = 1, #MM.shremls do - if ((MM.shremls[emeraldID].x == special.x) and (MM.shremls[emeraldID].y == special.y) and (MM.shremls[emeraldID].z == special.z)) - table.remove(MM.shremls, emeraldID) + for emeraldID = 1, #MM.shremds do + if ((MM.shremds[emeraldID].x == special.x) and (MM.shremds[emeraldID].y == special.y) and (MM.shremds[emeraldID].z == special.z)) + table.remove(MM.shremds, emeraldID) P_RemoveMobj(special) break end @@ -345,12 +345,12 @@ addHook("TouchSpecial", function(special, toucher) S_StartSound(toucher.player.mo, sfx_cgot, toucher.player) toucher.player.mm.role = ROLE_HERO toucher.player.mm.hud.roleflicker = 70 --2 secs - MM_ChatprintGlobal("SHREML_PICK") + MM_ChatprintGlobal("SHREMD_PICK") MM_StartShowdownMusic() end return true -end, MT_SHREML) +end, MT_SHREMD) -- -- Player Thinker @@ -371,33 +371,33 @@ addHook("PlayerThink", function(p) --role flickering timer if (p.mm.hud.roleflicker) p.mm.hud.roleflicker = $ - 1 end - --HUD flash screen fadeout - if (p.mm.hud.flashscrn) and (not (leveltime % 4)) - p.mm.hud.flashscrn = $ + 1 - if (p.mm.hud.flashscrn >= 10) p.mm.hud.flashscrn = 0 end + --HUD backend for fullscreen flash/spark effects + if (p.mm.hud.fx_translucency) and (p.mm.hud.fx_duration) and (not (leveltime & p.mm.hud.fx_duration)) + p.mm.hud.fx_translucency = $ + 1 + if (p.mm.hud.fx_translucency >= 10) p.mm.hud.fx_translucency = 0 end end --Sheriff Emerald Radar distance logic - if ((#MM.shremls) and ((p.mm.role == ROLE_INNOCENT) or (p.mm.role == ROLE_MURDERER)) and (not p.spectator)) --Murderers also need that number for the Anti-Camp system + if ((#MM.shremds) and ((p.mm.role == ROLE_INNOCENT) or (p.mm.role == ROLE_MURDERER)) and (not p.spectator)) --Murderers also need that number for the Anti-Camp system --find the distance to the closest emerald - for emeraldID = 1, #MM.shremls do - if (MM.shremls[emeraldID].valid) and (MM.shremls[emeraldID].timezone and (MM.shremls[emeraldID].timezone == p.mm.timetravel.timezone)) - table.insert(shreml_distances, #shreml_distances, P_AproxDistance(P_AproxDistance(p.mo.x - MM.shremls[emeraldID].x, p.mo.y - MM.shremls[emeraldID].y), p.mo.z - MM.shremls[emeraldID].z)) + for emeraldID = 1, #MM.shremds do + if (MM.shremds[emeraldID].valid) and (MM.shremds[emeraldID].timezone and (MM.shremds[emeraldID].timezone == p.mm.timetravel.timezone)) + table.insert(shremd_distances, #shremd_distances, P_AproxDistance(P_AproxDistance(p.mo.x - MM.shremds[emeraldID].x, p.mo.y - MM.shremds[emeraldID].y), p.mo.z - MM.shremds[emeraldID].z)) end end - shreml_closest = shreml_distances[0] - for emeraldID = 1, #shreml_distances do - if (shreml_distances[emeraldID] < shreml_closest) then shreml_closest = shreml_distances[emeraldID] end + shremd_closest = shremd_distances[0] + for emeraldID = 1, #shremd_distances do + if (shremd_distances[emeraldID] < shremd_closest) then shremd_closest = shremd_distances[emeraldID] end end - p.shreml_dist = shreml_closest + p.shremd_dist = shremd_closest --play sound - if (p.mm.shreml_dist) - if (p.mm.role == ROLE_INNOCENT) and (not SOC_IsTrue(mapheaderinfo[gamemap].disableradar)) - shreml_interval = MM_GetSHREMLinterval(fixint(p.mm.shreml_dist)) - if (shreml_interval and (leveltime % shreml_interval) == 0) S_StartSound(nil, sfx_emfind, p) end + if (p.mm.shremd_dist) + if (p.mm.role == ROLE_INNOCENT) and (not SOC_IsTrue(mapheaderinfo[gamemap].disableemeraldradar)) + shremd_interval = MM_GetSHREMLinterval(fixint(p.mm.shremd_dist)) + if (shremd_interval and (leveltime % shremd_interval) == 0) S_StartSound(nil, sfx_emfind, p) end elseif (p.mm.role == ROLE_MURDERER) and (CV_FindVar("mm_nocamping").value) - if (p.mm.shreml_dist < 25165824) --384*FU) + if (p.mm.shremd_dist < 25165824) --384*FU) p.mm.camping = $ + 1 if (p.mm.camping == 1050) then MM_PunishPlayer(p, "Emerald camping") end --kick player after 30 seconds of camping else p.mm.camping = 0 end diff --git a/SRC/LUA/HUD.LUA b/SRC/LUA/HUD.LUA index 38892e1..134fef6 100644 --- a/SRC/LUA/HUD.LUA +++ b/SRC/LUA/HUD.LUA @@ -14,7 +14,7 @@ local function wep2rw(wep) --convert WEP_* constant to RW_* constant return 2^(wep - 1) end -local function V_GetSHREMLiconID(dist) +local function V_GetSHREMDiconID(dist) if (dist < 256) return 6 elseif (dist < 512) return 5 elseif (dist < 1024) return 4 @@ -231,7 +231,7 @@ hud.add(function(v, p) v.drawString((hudinfo[HUD_LIVES].x + 18), hudinfo[HUD_LIVES].y, p.name, hudinfo[HUD_LIVES].f|V_ALLOWLOWERCASE|V_PERPLAYER|v.localTransFlag()) --Show your role - if ((p.mm.role) and (p.mm.role > ROLE_NONE) and (not (p.mm.hud.roleflicker % 4))) + if ((p.mm.role) and (p.mm.role > ROLE_NONE) and (not (p.mm.hud.roleflicker & 3))) V_DrawStrASCII(v, (hudinfo[HUD_LIVES].x + 18), (hudinfo[HUD_LIVES].y + 8), charset, MM.RoleColorHUD[p.mm.role]..MM_GetText(consoleplayer.mm.lang, "HUD_ROLES", p.mm.role), hudinfo[HUD_LIVES].f|V_PERPLAYER|v.localTransFlag()) end @@ -263,11 +263,11 @@ hud.add(function(v, p) if (MM.debug) error("\x82Tried to access \x87MM.text[\x80\""..consoleplayer.mm.lang.."\"\x87][\x80\"HUD_MIDJOIN\"\x87]\x82 that does not exist!\x80") end end end - if (p.mm.killedby) - if (p.mm.killedby == "your stupidity") + if (p.mm.killername) + if (p.mm.killername == "your stupidity") V_DrawStrASCII(v, hudinfo[HUD_RINGS].x, (hudinfo[HUD_RINGS].y), charset, "\21"..MM_GetText(consoleplayer.mm.lang, "HUD_KILLBY").."\16 "..MM_GetText(consoleplayer.mm.lang, "HUD_STUPID"), V_SNAPTOTOP|V_SNAPTOLEFT) else - V_DrawStrASCII(v, hudinfo[HUD_RINGS].x, (hudinfo[HUD_RINGS].y), charset, "\21"..MM_GetText(consoleplayer.mm.lang, "HUD_KILLBY").."\16 "..p.killedby, hudinfo[HUD_RINGS].f) + V_DrawStrASCII(v, hudinfo[HUD_RINGS].x, (hudinfo[HUD_RINGS].y), charset, "\21"..MM_GetText(consoleplayer.mm.lang, "HUD_KILLBY").."\16 "..p.mm.killername, hudinfo[HUD_RINGS].f) end end if ((not p.mm.minigame) and (not MM.twopgame) and (not MM.minigame)) @@ -401,7 +401,7 @@ hud.add(function(v, p) v.draw((MM.hud.game.pos.ringWep.x + 8 + weapon*20), (MM.hud.game.pos.ringWep.y), MM.graphics[MM.weapons[weapon][1]], V_PERPLAYER|V_SNAPTOBOTTOM|V_TRANSLUCENT|v.localTransFlag()) end end - if ((p.ammoremovaltimer) and ((leveltime % 8) < 4)) + if ((p.ammoremovaltimer) and ((leveltime % 7) < 4)) v.drawString((MM.hud.game.pos.ringWep.x + 8 + (p.ammoremovalweapon*20)), (MM.hud.game.pos.ringWep.y), "-"..p.ammoremoval, V_REDMAP|V_SNAPTOBOTTOM|V_PERPLAYER|v.localTransFlag()) --Ammo removal penalty end @@ -430,8 +430,8 @@ hud.add(function(v, p) end --Sheriff Emerald Radar for Innocents - if (p.mm.role == ROLE_INNOCENT) and (#MM.shremls) and (p.shreml_dist) and (not SOC_IsTrue(mapheaderinfo[gamemap].disableradar)) - v.drawScaled(9961472, 8912896, 32768, MM.graphics["IDEYAR"..V_GetSHREMLiconID(fixint(p.shreml_dist))], V_SNAPTOBOTTOM|v.localTransFlag()) --152*FU, 136*FU, FU/2 + if (p.mm.role == ROLE_INNOCENT) and (#MM.shremds) and (p.shremd_dist) and (not SOC_IsTrue(mapheaderinfo[gamemap].disableemeraldradar)) + v.drawScaled(9961472, 8912896, 32768, MM.graphics["IDEYAR"..V_GetSHREMDiconID(fixint(p.shremd_dist))], V_SNAPTOBOTTOM|v.localTransFlag()) --152*FU, 136*FU, FU/2 end --Are you alone? @@ -461,14 +461,9 @@ hud.add(function(v, p) V_DrawStrASCII(v, hudinfo[HUD_RINGS].x, (hudinfo[HUD_RINGS].y + 24), charset, MM_GetText(consoleplayer.mm.lang, "HUD_SNEAKING"), V_SNAPTOTOP|V_SNAPTOLEFT|V_PERPLAYER|v.localTransFlag(), true) end - --red Flash effect when you die - if (p.mm.hud.flashscrn) - v.drawStretched(0,0, (v.width() << FRACBITS), (v.height() <> 1))) << FRACBITS, (MM.hud.scores.pos.teammateInfo.y + ((teammateNo % 2) << 4)) << FRACBITS, 32768, v.getSprite2Patch(p.skin, SPR2_XTRA), v.localTransFlag(), v.getColormap(p.skin, p.skincolor)) --FU/2 + v.drawScaled((MM.hud.scores.pos.teammateInfo.x + (136*(teammateNo >> 1))) << FRACBITS, (MM.hud.scores.pos.teammateInfo.y + ((teammateNo & 1) << 4)) << FRACBITS, 32768, v.getSprite2Patch(p.skin, SPR2_XTRA), v.localTransFlag(), v.getColormap(p.skin, p.skincolor)) --FU/2 --player name (colored as role) - v.drawString((MM.hud.scores.pos.teammateInfo.x + 18 + (136*(teammateNo >> 1))), (MM.hud.scores.pos.teammateInfo.y + ((teammateNo % 2) << 4)), MM.RoleColor[p.mm.role]..p.name, V_ALLOWLOWERCASE|v.localTransFlag()) + v.drawString((MM.hud.scores.pos.teammateInfo.x + 18 + (136*(teammateNo >> 1))), (MM.hud.scores.pos.teammateInfo.y + ((teammateNo & 1) << 4)), MM.RoleColor[p.mm.role]..p.name, V_ALLOWLOWERCASE|v.localTransFlag()) --icon of the currently held weapon - v.drawScaled((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + (136*(teammateNo >> 1))) << FRACBITS, (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo % 2) << 4)) << FRACBITS, 32768, MM.graphics[MM.weapons[p.currentweapon][1]], v.localTransFlag()) --FU/2 + v.drawScaled((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + (136*(teammateNo >> 1))) << FRACBITS, (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo & 1) << 4)) << FRACBITS, 32768, MM.graphics[MM.weapons[p.currentweapon][1]], v.localTransFlag()) --FU/2 --amount of currently held weapon ammo - v.drawString((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + 18 + (136*(teammateNo >> 1))), (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo % 2) << 4)), p.powers[pw_infinityring + p.currentweapon], v.localTransFlag(), "thin") + v.drawString((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + 18 + (136*(teammateNo >> 1))), (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo & 1) << 4)), p.powers[pw_infinityring + p.currentweapon], v.localTransFlag(), "thin") --red ring icon - v.drawScaled((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + MM.hud.scores.pos.teammateInfoOffset2.x + (136*(teammateNo >> 1))) << FRACBITS, (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo % 2) << 4)) << FRACBITS, 32768, MM.graphics[MM.weapons[-1][1]], v.localTransFlag()) --FU/2 + v.drawScaled((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + MM.hud.scores.pos.teammateInfoOffset2.x + (136*(teammateNo >> 1))) << FRACBITS, (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo & 1) << 4)) << FRACBITS, 32768, MM.graphics[MM.weapons[-1][1]], v.localTransFlag()) --FU/2 --amount of [red] rings - v.drawString((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + MM.hud.scores.pos.teammateInfoOffset2.x + 18 + (136*(teammateNo >> 1))), (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo % 2) << 4)), p.rings, v.localTransFlag(), "thin") + v.drawString((MM.hud.scores.pos.teammateInfo.x + MM.hud.scores.pos.teammateInfoOffset1.x + MM.hud.scores.pos.teammateInfoOffset2.x + 18 + (136*(teammateNo >> 1))), (MM.hud.scores.pos.teammateInfo.y + 8 + ((teammateNo & 1) << 4)), p.rings, v.localTransFlag(), "thin") teammateNo = $ + 1 end end @@ -554,7 +549,7 @@ hud.add(function(v) if (PlayerCount(ROLE_INNOCENT)) V_DrawStrASCII(v, 20, 192, charset, (MM.RoleColorHUD[ROLE_INNOCENT]..MM_GetText(consoleplayer.mm.lang, "HUD_ROLESALIVE", ROLE_INNOCENT)..": "..PlayerCount(ROLE_INNOCENT)), v.localTransFlag()) end --"Sheriff's Emerald is available!" - if ((#MM.shremls) and (leveltime & 1)) + if ((#MM.shremds) and (leveltime & 1)) v.drawScaled(524280, 12058440, 32768, MM.graphics["CHAOS3"], v.localTransFlag()) --8*FU, 184*FU, FU/2 end end @@ -562,14 +557,9 @@ hud.add(function(v) --Online v.drawString(160, 176, "ONLINE: "..PlayerCount(), v.localTransFlag()) - --red Flash effect when you die - if (consoleplayer.mm.hud.flashscrn) - v.drawStretched(0,0, (v.width() << FRACBITS), (v.height() <> 1)).."0" + local hazardSprite = "SPIK"..string.char(65 + ((leveltime & 15) >> 1)).."0" for id, hazard in pairs(p.SonicRun.hazards) v.drawScaled((coords.sonicRun.x + hazard.x + 14)*FU, (coords.sonicRun.y + (80 - hazard.y))*FU, 32768, v.cachePatch(hazardSprite)) --FU/2 end diff --git a/SRC/LUA/TEXT/EN.LUA b/SRC/LUA/TEXT/EN.LUA index d8b269e..16a4650 100644 --- a/SRC/LUA/TEXT/EN.LUA +++ b/SRC/LUA/TEXT/EN.LUA @@ -186,7 +186,7 @@ local language_data = { --Language must be a table variable, you can name the va ["DIED_HAZARD"] = "has died in an accident", --Sheriff's Emerald pickup global notification - ["SHREML_PICK"] = "Someone picked up the \x84Sheriff's Emerald\x80...", + ["SHREMD_PICK"] = "Someone picked up the \x84Sheriff's Emerald\x80...", --Player has killed someone it did not have to ["KILL_PUNISHMENT_PM"] = { diff --git a/SRC/LUA/TEXT/ES.LUA b/SRC/LUA/TEXT/ES.LUA index 3ed4274..7435a63 100644 --- a/SRC/LUA/TEXT/ES.LUA +++ b/SRC/LUA/TEXT/ES.LUA @@ -93,7 +93,7 @@ MM.AddLang("ES", { "\x80".."fue asesinado!" }, ["DIED_HAZARD"]="ha muerto en un accidente", - ["SHREML_PICK"]="Alguien ha tomado la\x84 Esmeralda del Comisario\x80...", + ["SHREMD_PICK"]="Alguien ha tomado la\x84 Esmeralda del Comisario\x80...", ["KILL_PUNISHMENT_PM"]={ "\x87Has matado a un \x83Inocente\x87! Has sido despedido!. (Ya no eres un Comisario)", "Los \x82Heroes\x87 no estan hechos para matar \x83Inocentes\x87. Conseguiste la penalizacion de muerte por eso." diff --git a/SRC/LUA/TEXT/FR.LUA b/SRC/LUA/TEXT/FR.LUA index 2037d62..c19ce2e 100644 --- a/SRC/LUA/TEXT/FR.LUA +++ b/SRC/LUA/TEXT/FR.LUA @@ -93,7 +93,7 @@ MM.AddLang("FR", { "\x80".."a ete assassiner!" }, ["DIED_HAZARD"]="est mort dans un accident", - ["SHREML_PICK"]="Quelqu'un a pris la \x84Sheriff's Emerald\x80...", + ["SHREMD_PICK"]="Quelqu'un a pris la \x84Sheriff's Emerald\x80...", ["KILL_PUNISHMENT_PM"]={ "\x87Vous avez tuer un \x83Innocent\x87! ous etes virez. (You're no longer a Sheriff)", "Les \x82Heros\x87 ne doivent pas tuer les \x83Innocents\x87. Vous avez la penaliter de morts pour ca." diff --git a/SRC/LUA/TEXT/PL.LUA b/SRC/LUA/TEXT/PL.LUA index 330ad30..2747059 100644 --- a/SRC/LUA/TEXT/PL.LUA +++ b/SRC/LUA/TEXT/PL.LUA @@ -93,7 +93,7 @@ MM.AddLang("PL", { "\x80zostal zamordowany!" }, ["DIED_HAZARD"]="zginal(ela) w nieszczesnym wypadku", - ["SHREML_PICK"]="Ktos podniosl \x84Szmaragd Szeryfa\x80...", + ["SHREMD_PICK"]="Ktos podniosl \x84Szmaragd Szeryfa\x80...", ["KILL_PUNISHMENT_PM"]={ "\x87Zamordowales \x83Niewinnego\x87! Nie jestes juz \x84Szeryfem\x87!", "\x82".."Bohaterowie nie sa po to, zeby zabijac \x83Niewinnych\x87. Masz za to kare smierci.", diff --git a/SRC/LUA/TEXT/RU.LUA b/SRC/LUA/TEXT/RU.LUA index f7f834e..84863a1 100644 --- a/SRC/LUA/TEXT/RU.LUA +++ b/SRC/LUA/TEXT/RU.LUA @@ -95,7 +95,7 @@ MM.AddLang("RU", { "\x80".."byl ubit!" }, ["DIED_HAZARD"]="popal(a), kuda ne sledovalo", - ["SHREML_PICK"]="Kto-to podobral \x84Izumrud Sherifa\x80...", + ["SHREMD_PICK"]="Kto-to podobral \x84Izumrud Sherifa\x80...", ["KILL_PUNISHMENT_PM"]={ "\x87Ty ubil(a) \x83Nevinnogo\x87! Ty bolshe ne Sherif!", "\x82Geroi\x87 ne sozdany, chtob ubivat' \x83Nevinnyh\x87. Za eto budet otvetnaya smert'.", diff --git a/SRC/LUA/TEXT/TR.LUA b/SRC/LUA/TEXT/TR.LUA index f201307..5e2d275 100644 --- a/SRC/LUA/TEXT/TR.LUA +++ b/SRC/LUA/TEXT/TR.LUA @@ -94,7 +94,7 @@ MM.AddLang("TR", { "\x80olduruldu!" }, ["DIED_HAZARD"]="bir kazada oldu", - ["SHREML_PICK"]="Birisi \x84Serif'in Zumrutu\x80'nu aldi...", + ["SHREMD_PICK"]="Birisi \x84Serif'in Zumrutu\x80'nu aldi...", ["KILL_PUNISHMENT_PM"]={ "Bir\x87 \x83Masum\x87'u oldurdun! Kovuldun. (Artik bir Serif degilsin)", "\x82Kahramanlar\x87, \x83Masumlar\x87'i oldurmek icin tasarlanmamistir. Bunun icin idam cezasi aldiniz.", diff --git a/SRC/LUA/TEXT/UA.LUA b/SRC/LUA/TEXT/UA.LUA index 3e1f9df..ccd1232 100644 --- a/SRC/LUA/TEXT/UA.LUA +++ b/SRC/LUA/TEXT/UA.LUA @@ -89,7 +89,7 @@ MM.AddLang("UA", { -- Ukrainian by LeonardoTheMutant "\x80wbytyj!" }, ["DIED_HAZARD"]="zagynuw(la) u neschasnomu wypadku", - ["SHREML_PICK"]="Htos' uziaw \x84Smaragd Sheryfa\x80...", + ["SHREMD_PICK"]="Htos' uziaw \x84Smaragd Sheryfa\x80...", ["KILL_PUNISHMENT_PM"]={ "\x87Wy wbyly \x83Newynnogo\x87! Was zwil'neno! (Ty bil'she ne Sheryf)", "\x82Geroji\x87 ne majut' prawa wbywaty \x83Newynnych\x87! Was zasudzheno na smert' za wash zlochyn!", diff --git a/SRC/LUA/TIMETRAVEL.LUA b/SRC/LUA/TIMETRAVEL.LUA index 0755322..bde569b 100644 --- a/SRC/LUA/TIMETRAVEL.LUA +++ b/SRC/LUA/TIMETRAVEL.LUA @@ -203,7 +203,7 @@ addHook("PlayerThink", function(p) end end end - p.mm.timetravel.spark = 1 + MM_StartFlashFX(p, 7, 0) --P_SpawnMobjFromMobj(p.mo,0,0,0,MT_THROWNEXPLOSION) --blast after a time warp (visual effect) S_StartSound(p.mo, sfx_mixup, p) p.mm.timetravel.timesign = TWS_NONE @@ -215,12 +215,6 @@ addHook("PlayerThink", function(p) p.mm.timetravel.warptimer = 0 end end - - --reduce spark opacity after time warp - if (p.mm.timetravel.spark and (leveltime % 8 == 0)) - p.mm.timetravel.spark = $ + 1 --increasing the translucenty level - if (p.mm.timetravel.spark >= 10) p.mm.timetravel.spark = 0 end - end end) -- diff --git a/SRC/NOTES4HOSTERS.TXT b/SRC/NOTES4HOSTERS.TXT index 26c1771..83937cc 100644 --- a/SRC/NOTES4HOSTERS.TXT +++ b/SRC/NOTES4HOSTERS.TXT @@ -3,14 +3,14 @@ for those who are going to host this addon pack on their server (including you) ---=== HOW TO LAUNCH THE LTM'S MURDER MYSTERY GAME ===--- A. From the command line: - 1) Add the game-type addon file with "-FILE [path_to_the_addon]" parameter; - 2) Write the name of the gametype to launch like: + 1. Add the game-type addon file with "-FILE [path_to_the_addon]" parameter; + 2. Write the name of the gametype to launch like: -gametype LTM_MM - 3) You probably don't want to start from Greenflower1 so you need to use "-WARP MAPK0" + 3. You probably don't want to start from Greenflower1 so you need to use "-WARP MAPK0" to start from MM maps. The final command line should be something like: - srb2win.exe -server (-dedicated) -file [place_where_addon_located]/MM_MurderMystery-v[ver].pk3 -gametype LTM_MM -warp MAPK0 + [your_SRB2_executable] -server (-dedicated) -file [path_to_the_addon] -gametype LTM_MM -warp MAPK0 B. From the in-game console: MAP [MMmapnum] -GAMETYPE LTM_MM diff --git a/SRC/README.TXT b/SRC/README.TXT index e303d51..375c3d8 100644 --- a/SRC/README.TXT +++ b/SRC/README.TXT @@ -30,7 +30,7 @@ translations | English, Polish, Russian, Turkish, Ukrainian * The add-on was designed to not modify the vanilla aspects of the game. There is only one known bug where Metal Sonic can't get into his Hyper Dash mode when playing in vanilla game types with MM add-on present -** Please read READ_BEFORE_HOSTING.TXT for details +** Please read NOTES4HOSTERS.TXT for details *** Digital Music pack is separate and can be downloaded from the SRB2 MM's GitHub repository @@ -40,30 +40,30 @@ translations | English, Polish, Russian, Turkish, Ukrainian ============================================================ SRB2MM_DEV team is: - LeonardoTheMutant - "CEO of the project", Mapper, Coder, Visual Design, Ukrainian, Russian & Polish translator + LeonardoTheMutant - Leader of the project, Coder, Mapper, Visual Design, Ukrainian, Russian & Polish translator, Ambassador of Europe + MinusMario - "The Veteran of MM", Music Composer + Troplucky - "The Official Bob representative in MM", Mapper, Music management, French translator Jesus.B - Coder, Spanish translator - Troplucky - Mapper, Music management, French translator - Arnie37, Sonic1983 - Russian translator(s) - SlainLBS - Spanish translator + Arnie37, Sonic1983 - Russian translators Mobillia - Turkish translator asdhio (aheiiv) - Ukrainian translator LexTheGamer95 - Ambassador of North America lamon - Ambassador of the United Kingdom Former members: - tedbasher3000 (AKA tedvin11) - Coder + tedbasher3000 (AKA tedvin11) - Former Leader Coder futuresmiles - Ambassador of North America - SuperOfSRB2 - Ambassador of North America + SuperOfSRB2 - Ambassador of North America, Mapper White Tails {UKR} - Ambassador of Lituana sopix - Polish translator + SlainLBS - Spanish translator Piksqu - Mapper & French translator - King Jonas - Ambassador of Brazil & Portuguese translator + King Jonas - Ambassador of Brazil, Portuguese translator ToeiSamurai - Coder Special Thanks to: - tedvin11 for the idea, base code, and leadership during the very early development - Musicians from FREEDOOM community for the wonderful map MIDIs - - King Meteor for his high-quality MIDI arrangements of songs from Sonic games - Collision Chaos Radio for Sonic CD Music restoration - "MM2 in Roblox" & "MM in Minecraft" for the inspiration - Jisk for having an extremely negative opinion on us and our project @@ -77,7 +77,7 @@ and Thank YOU for playing this add-on! -If you are going to host this game type yourself please read the READ_BEFORE_HOSTING.TXT file for +If you are going to host this game type yourself please read the NOTES4HOSTERS.TXT file for the correct server setup and important notes. If you're interested in modding this game type please take a look at our GitHub repository and/or diff --git a/SRC/SOC/MAINCFG.TXT b/SRC/SOC/MAINCFG.TXT index 22cca28..1362b85 100644 --- a/SRC/SOC/MAINCFG.TXT +++ b/SRC/SOC/MAINCFG.TXT @@ -38,7 +38,7 @@ TypeOfLevel = LTM_MM SkyNum = 17 Weather = 2 NextLevel = K4 -Lua.Autor = Jisk, LeoTM +Lua.Autor = Zombie Escape team, LeoTM Level K4 LevelName = West City @@ -57,7 +57,7 @@ Act = 0 SkyNum = 30 TypeOfLevel = LTM_MM NextLevel = K6 -Lua.Author = LeoTM, Rare +Lua.Author = Rare, LeoTM Level K6 LevelName = BACKROOMS @@ -135,7 +135,7 @@ Lua.Timelimit = 11 NextLevel = KD Lua.ShowdownTrack = 11H_TR Lua.SlowWalkSpeed = True -Lua.DisableRadar = True +Lua.DisableEmeraldRadar = True Lua.DisableFootmarks = True Lua.Author = Trillobyte, LeoTM diff --git a/TOOLS/CONVERTERS/HEX2LUA.C b/TOOLS/CONVERTERS/HEX2LUA.C index 84f3068..f2c0996 100644 --- a/TOOLS/CONVERTERS/HEX2LUA.C +++ b/TOOLS/CONVERTERS/HEX2LUA.C @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) hexWritten = 0; } else { //print as an Escape Code (compression disabled or failed to convert) - if (!(hexWritten % 2)) //Writing an 8-bit Escape Code + if (!(hexWritten & 1)) //Writing an 8-bit Escape Code { printf("\\x%X", int_symbol); } else { //We are allowed to write another value to make a 16-bit code diff --git a/TOOLS/CONVERTERS/PATCH2TXT.C b/TOOLS/CONVERTERS/PATCH2TXT.C index 2e395f4..8255c91 100644 --- a/TOOLS/CONVERTERS/PATCH2TXT.C +++ b/TOOLS/CONVERTERS/PATCH2TXT.C @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) hexWritten = 0; } else { //compression disabled or non-convertable symbol, write in HEX format - if (!(hexWritten % 2)) fprintf(outputfile, "\\x%02X", currPixel); //Writing an 8-bit Escape Code + if (!(hexWritten & 1)) fprintf(outputfile, "\\x%02X", currPixel); //Writing an 8-bit Escape Code else fprintf(outputfile, "%02X", currPixel); //We are allowed to write another value to make a 16-bit code hexWritten++; } diff --git a/docs/index.html b/docs/index.html index df4c059..3479b69 100755 --- a/docs/index.html +++ b/docs/index.html @@ -9,55 +9,57 @@

LeonardoTheMutant's Murder Mystery

-
- -
-
Murder Mystery box art
-
-
-

The port of the famous multiplayer game in SRB2!

-

This project tries to make an SRB2 gametype similar to "Murder Mystery 2" on Roblox and make it feel like a Sonic game. The development originally started by Tedbasher3000 in February 2023 and continued by the SRB2MM_DEV team to this day. Even though the project is still in ALPHA state the game is pretty playable and can be hosted on public servers

-

Short introduction into the gameplay

-

The goal of this game is to detect and eliminate all Murderers among the players before they kill everyone (sounds very familiar, right?). Sheriffs are given the task to prevent this genocide and protect all Innocents from being murde#dc143c.

-

At the beginning of each round you will recieve one of these 3 roles. As said, Murderers have to murder everyone, Sheriffs have to defend Innocents and eliminate Murderers & Innocents have to hide from the killers but can also help in the investigation.

-

You can find more description with all the details inside the Add-On in MMHELP console command.

-

Want to contribute? That's great!

-

We made the SRB2MM_DEV Discord server and a GitHub repository just for cases like this!
You can make any kind of contribution including new maps, music, ideas or even make a translation of the add-on to your native language! You can also join our Discord if you want talk with the developers and other players.

-
-
-
-

Recommended System Requirements for the gametype

-
    -
  • A computer capable of running Sonic Robo Blast 2
  • -
  • 640x400 VGA monitor
  • -
  • Keyboard+Mouse or the 2-axis gamepad for the controls
  • -
  • Stereo sound output system (better with headphones) with enabled in-game closed captions
  • -
  • 150ms or faster ping connection with the game server
  • -
  • Fast reaction time or faster
  • -
  • A Human® brain capable of running NI (Natural Intelligence) and CriticalThinking™ technology support
  • -
-

If your system does not meet one of these requirements, you are pretty much DOOM™ed

-
-
-
-

Download the LTM's Murder Mystery Add-On (latest version: 10.1-BETA)

- -

Older versions and builds of the Add-On can be found in the #release-builds channel on our Discord server or in the repository's Releases page

-
-
- -
+
+
+ +
+
Murder Mystery box art
+
+
+

The port of the famous multiplayer game in SRB2!

+

This project tries to make an SRB2 gametype similar to "Murder Mystery 2" on Roblox and make it feel like a Sonic game. The development originally started by Tedbasher3000 in February 2023 and continued by the SRB2MM_DEV team to this day. Even though the project is still in ALPHA state the game is pretty playable and can be hosted on public servers

+

Short introduction into the gameplay

+

The goal of this game is to detect and eliminate all Murderers among the players before they kill everyone (sounds very familiar, right?). Sheriffs are given the task to prevent this genocide and protect all Innocents from being murde#dc143c.

+

At the beginning of each round you will recieve one of these 3 roles. As said, Murderers have to murder everyone, Sheriffs have to defend Innocents and eliminate Murderers & Innocents have to hide from the killers but can also help in the investigation.

+

You can find more description with all the details inside the Add-On in MMHELP console command.

+

Want to contribute? That's great!

+

We made the SRB2MM_DEV Discord server and a GitHub repository just for cases like this!
You can make any kind of contribution including new maps, music, ideas or even make a translation of the add-on to your native language! You can also join our Discord if you want talk with the developers and other players.

+
+
+
+

Recommended System Requirements for the gametype

+
    +
  • A computer capable of running Sonic Robo Blast 2
  • +
  • 640x400 VGA monitor
  • +
  • Keyboard+Mouse or the 2-axis gamepad for the controls
  • +
  • Stereo sound output system (better with headphones) with enabled in-game closed captions
  • +
  • 150ms or faster ping connection with the game server
  • +
  • Fast reaction time or faster
  • +
  • A Human® brain capable of running NI (Natural Intelligence) and CriticalThinking™ technology support
  • +
+

If your system does not meet one of these requirements, you are pretty much DOOM™ed

+
+
+
+

Download the LTM's Murder Mystery Add-On (latest version: 10.1-BETA)

+ +

Older versions and builds of the Add-On can be found in the #release-builds channel on our Discord server or in the repository's Releases page

+
+
+ +
+
+ diff --git a/docs/style.css b/docs/style.css index 7ab08e4..92d9300 100755 --- a/docs/style.css +++ b/docs/style.css @@ -1,4 +1,4 @@ -body{ +body { background-color: #222222; color: white; font-family: arial; @@ -9,21 +9,31 @@ body{ border-style: solid; border-color: red } -header{ + +header { padding: 5px; background-color: #111111; } -h3{ + +footer { + padding: 5px; + background-color: #111111; +} + +h3 { color: orange; } -#download h3{ + +#download h3 { color: #5555ff; } -hr{ + +hr { background-color: red; border: none; height: 2px; } + img { border: 4px dashed; border-color: blue;