Skip to content
Shararvev edited this page Jun 12, 2023 · 14 revisions

Эта страница доступна на Русском

Introduction

The engine has the feature to add outputs in runtime via the AddOutput input. This feature was actively used by mappers of multiplayer maps in games such as Counter-Strike: Source, Synergy, Obsidian Conflict, etc. I made similar maps for the Obsidian Conflict mod in the period of 2010-2012. With the help of AddOutput, it was possible to "programming" - to create gamemodes, economy, inventory on players, special NPCs, special entities. But at that time, VScript didn't even exist yet!

Although this system is flexible, it is very inconvenient and cumbersome. What is described above was an incredible madness of a million entities in Hammer, similar to the progenitor of Blueprints From Hell. But even now, to make a simple elevator logic with buttons, you have to create several logical entities, and then link it all together. To fix any logical error, you have to completely recompile the map.

At some point, I got tired of this, I decided to remove all the logic from Hammer and move it to Lua, so that we wouldn't have to recompile the map for the one button. Or another lame option is to create your own scripted entity of buttons/doors/elevators.

Basic knowledge

Map Logic Controller (MapLogic) allows you to setup the Inputs/Outputs logic on map from Lua. If you don't understand what I'm talking about, please refer to the official documentation Valve Developer Wiki.

The controller uses AddOutput input to add new outputs to entities: https://developer.valvesoftware.com/wiki/AddOutput

To catch these outputs in Lua, the controller uses the method ENTITY:AcceptInput: https://wiki.facepunch.com/gmod/ENTITY:AcceptInput

The controller is a server-side point entity, which makes it possible to create outputs in Lua scripts for map entities. Thanks to this, you can easily configure the complex logic of mechanisms, elevators, doors, combination locks, trains - everything that in Hammer turns into a living hell of dozens of logic entities, millions of outputs, and is often an impossible task.

Technically map_logic_controller recognizes inputs and calls the binded Lua functions. These inputs are a callback from the outputs added using AddOutput. Outputs are added in the code via the MetaTarget object in the OnMapLogicInitialized hook.

Additionally don't miss:

Console commands

  • Console command map_logic_reload - Removes the old controller and creates a new one. Forces the entire map logic to be initialized again. Please don't use this too many times (see below).

  • Console variable map_logic_override "" - Overrides map name for which the controller will initialize the logic. This way, you can make several presets for one map. The value of the variable is not saved, so you need to set it when the server starts in autoexec.cfg or server.cfg.

A few simple rules

  • Do not create the controller too often. Each logic initialization adds outputs for a new controller. If the controller is removed, then the outputs fires into the void - there is nothing wrong with that, but if there are hundreds or thousands of outputs, it will cause a serious drop in performance inside the engine. You can clean up the map gmod_admin_cleanup or manually delete outputs using Entity:ClearAllOutputs, however centralized deletion can't be implemented.

  • Do not create multiple controllers at the same time. In any case, the code is written so that only one of them will work, but the first one will be called, and the functions will be overwritten by the last one, I can't predict how this may behave.

  • The controller is created when starting the map in the InitPostEntity hook with name MapLogicSpawn, and when clearing the map in the PostCleanupMap hook with name MapLogicSpawn, you do not need to spawn it. If you want to recreate the controller, first remove the old one, or use the console command map_logic_reload.

Useful tips for mappers

  • Unlock all elevator doors in Hammer to avoid writing extra code.

  • The sounds of the elevator buttons are more convenient to play in Lua, so you can determine whether your script is working.

  • Repeat the elevator path from path_track to the ring for autorefresh. Otherwise, your elevator may get stuck.

Security recommendations

It is important to understand that I am not responsible for the scripts that people make for their maps. This entity is not an alternative to lua_run, it does't execute code and is not created from Hammer. This entity is designed to give easy control over the map logic from Lua scripts, but everything that the script author will write is on his conscience.

Do not try to embed the script in your map or hide it somehow, or even worse, obfuscate/encrypt it. You can distribute your script in an addon with a map or a separate addon. In one addon, you can put a lot of logic presets at once, including for different maps.

On Lua you can do anything, starting from simple prank, ending with major security things. Do not try to create secret buttons that give some goods or admin-access to player. This is similar to what if you used lua_run for fun, don't do that! Please note that it is bad form to check access to secret rooms by SteamID. Please do not kick or ban players on your maps, this is a very bad thing.

Use cases

In general, with this addon, you can easily create logical things that are too cumbersome in Hammer. Elevator from func_tracktrain for 5 floors? Easy! As usual, create an elevator, its path from path_track, 5 buttons in the elevator and each on the floor. Give them all a name, you don't need anything else in Hammer. Now just get these entities in the code, and write all logic in Lua - add the necessary outputs and call the inputs via Entity:Fire to open the doors and start/stop the elevator. You don't even need to setup the sounds in Hammer, because they can be played directly from Lua!

For RP maps, you can, for example, make a private buttons for certain jobs. You can setup the logic for different gamemodes, events, weathers or seasons, and switch them using map_logic_override. You can change or fix the logic on existing maps, you can delete outputs using Entity:ClearAllOutputs. If you rename the necessary entities, this will completely mute the inputs, but this will not work on outputs with Keywords !activator, !self, !player. Alternatively, you can mute them all via GM:AcceptInput.

For gamemode specific maps, you can do things like repairing mechanisms, interactive start of the generator in zombie-modes, electronic combination locks. You can, for example, give the opportunity to break the elevator, and then fix it, or disable certain floors. All this is impossible in Hammer, but in your scripts you can control it as you like, any bug can always be fixed.

For a coop-maps or a story-maps, you can setup the NPC spawn logic, control waves of enemies and the spawn of bosses. Launch complex scenes by triggers and buttons, give players ammunition and weapons without ugly manipulations with Hammer entities! You can easily use all advantages of Lua, create timers, logical if else, switch-case, mathematical operations, calculating integrals, getting computer time... The possibilities of using this addon are limited only by your imagination.