Creeper, aw man

From SRB2 Wiki
Jump to navigation Jump to search

Using State as template for this page. :earless:
Felt like writing down what could a custom gamemode framework of sorts be like.
A gamemode, or a gametype (not exactly the same thing?), is a distinct configuration that varies gameplay and affects how other game mechanics behave. just writing this here, it's handy

What if...

Gamemodes are referenced by a constant. 0 for Singleplayer/Co-op, 1 for competition, and so on. States, objects, sprites(?) and sound effects are also referenced (internally) by a constant!
The game has free space to allow modders to allocate their own objects/states/what have you, and then reference them by a constant with a "random" number assigned to it (more like the first available slot).
Therefore, we could do the same with custom gamemodes! Freeslot could be used to "create" a new gamemode by using the GT_ prefix, allowing us to reference it later on.

Attributes

Gamemodes would have "attributes" that would define if the game would carry out some vanilla actions on specific circumstances or not.

  • Name: The name that would show up in the hosting screen when scrolling through gametypes.
  • Flag: A flag for the Level header to use.
  • CanUse: A list of gametype flags, separated by commas, signaling the game that this gametype can alternatively use levels that contain any of these TypeOfLevel flags.
  • Spectators: Whether this gametype allows spectating. An 1 would allow players to enter spectator mode, while a 0 would force everyone into the game, like Co-op.

To add to this, if the gametype changes from a non-spectators one to another with spectators, everyone will be immediately sent to spectator.

  • Teams: A comma separated list of stylized team names. If this value exists, Enter game... is replaced by Switch team... with a list of available teams using the names set here, along with the spectator team if applicable. Each team is assigned a number, just like red is 1 and blue is 2 in CTF, and so on. The modder is then tasked on handling colors and the HUD.

Same as above, if the gametype changes from one without teams to one with teams, everyone is sent to spectator. However, everyone will remain in their playing state if changing from a teamed gametype to a non-teamed one.

  • UseRespawnDelay: If 1, whether the game delays respawning, using the respawndelay CVar.
  • WeaponRings: If 1, ringslinger is forced on. This allows the default weapon rings to spawn in the map, and shows the weapon selector.
  • Emeralds: If 1, spawn vanilla match emeralds in their respective spawn points.
  • TimeLimit: Default time limit value for this gametype.
  • PointLimit: Default point limit value for this gametype. For this value and the above, a host switching gametypes will make the game read these two values and apply them once, as to "initialize" the default limits.
  • :
    • :

Level header?

Levels have a TypeOfLevel value which tells the game, well, what type of level is it. Is it for Co-op? For race? For match?
If you freeslot a gametype, you are forced to enter a flag name, the which you can now use as a TypeOfLevel flag of sorts. Even if the flag wasn't defined, you should be able to use it regardless - It wouldn't work, of course, but once a gamemode adds such flag, it will be used.

Level/Gamemode attribute interaction

When generating a list of maps a gametype can use (does the game even do this? Imagine it does), the game could look for levels containing either the gamemode specific flag, or flags specified by the gamemode in CanUse.
For example, Chaos works on both chaos specific maps and in match maps. The gamemode was defined with CanUse having the value of Match.
When the game makes the list, it will look for maps with TypeOfLevel containing either Chaos or Match, and adds it to the list if there was a match.

Lua interaction

As this is aimed to Lua scripting, modders could be given more tools to handle their gametype.

The game should expose both time limit and point limit to Lua as a read and write variable - That way, the modder doesn't have to create a separate CVar for their gametype's scoring methods, and also set some restraints.
On top of that, vanilla behaviour of ending the map when reaching the time/point limit should be disabled, allowing the modder to decide when to actually end the map, for example because of there being some sort of tie-breaker period, or just creating an animation on round end.

inttime should be an exposed read only variable, specifically for the intermission hooks.

An intermission HUD hook would allow modders to customize the rankings screen with information relevant to their gametype, with a default level screenshot as the default backdrop and the inttime counter at the bottom. That way they can display team score, winners, something resembling the Co-op level end screen, and so.

Also, hooks!

Non-HUD hooks

ViewpointSwitch

Hook format: addHook("ViewpointSwitch", functionname)

Function format: function(player_t player, player_t targetplayer)

Function return value: Boolean (allow switch?)

When a player presses the Change Viewpoint button, this hook is called to decide whether the next player is suitable as a viewpoint.
This calls the function given with the player next in the list starting from the current player. Should this return false, the hook will then be called with the next player in the list, looping around if we reached the end. If this returns true, the loop ends and the viewpoint is changed to targetplayer.

For example, if there is a team gametype with red and blue teams, you wouldn't want the living to be able to spectate their opponents, while spectators can spectate any player.
If a red team member changes viewpoints, ViewpointSwitch could be called with the targetplayer being in the blue team. Returning false will then call this function again with the next person in line until reaching either another red team member or themselves, then which the hook would return true and change viewpoints accordingly.

TeamSwitch

Hook format: addHook("TeamSwitch", functionname)

Function format: function(player_t player, number team)

Function return value: Boolean (allow switch?)

Whether player can switch to team team. Returning false would slow the player a "Can't switch to this team" message.
There may be events in the which the modder would want to prevent team switching, as to prevent cheating or otherwise.

Other interactions

How would the master server identify these gametypes if they are sent as a number?
Maybe the master server could report a "custom" or "unknown" gametype if it doesn't match any of the vanilla values.
Or the game could additionally send the gametype string and other gametype related data to the master server, the which can't use anyways lol

SOC definition

An example of a gamemode definition written with SOC. I'm not exactly experienced with SOC, but this is a general idea.

Freeslot
GT_CHAOS

Gametype GT_CHAOS
Name = Chaos
Flag = Chaos
CanUse = Match,CTF

Level MC
Name = Probably a valid map
TypeOfLevel = Match,Chaos
Freeslot
GT_BATTLERACE # lol cool name

Gametype GT_BATTLERACE
Name = Battle Race
Flag = BattleRace
CanUse = Race,SP,Co-op,Competition

Level 1
Name = Yellowdandelion Area
TypeOfLevel = SP,Race,All of these flags up there

Level 99
Name = A battle race specific map
TypeOfLevel = Race,BattleRace

Lua definition?

This page was more or less aimed for gamemode implementation using SOC for Lua to access later, but I didn't get to this part yet :^)