Giter VIP home page Giter VIP logo

dreamycecil / advancedmultiplayer2 Goto Github PK

View Code? Open in Web Editor NEW
2.0 1.0 0.0 27.52 MB

A mod for classic Serious Sam: The Second Encounter v1.07 that adds a lot of options for multiplayer games including coop mode support for singleplayer maps.

License: GNU General Public License v2.0

Batchfile 0.01% C++ 96.81% C 0.94% Clarion 0.43% ECL 0.01% HTML 0.42% Visual Basic 6.0 1.40%
serious-sam serious-engine sdk mod open-source sam-sdk

advancedmultiplayer2's Introduction

Advanced Multiplayer 2 Mod

This is the source code of a mod for classic Serious Sam: The Second Encounter v1.07 that adds a lot of options for multiplayer games including coop mode support for singleplayer maps. Based on Serious Engine 1 Mod SDK

Building

Building instructions are available here: https://github.com/DreamyCecil/SE1-ModSDK/wiki/Building

Running

Once the project is compiled, there should be three libraries in the Bin folder: EntitiesMP.dll, GameGUIMP.dll and GameMP.dll.

There are two ways to start the mod:

  1. Create a .des file in your Mods directory under the same name as this repository, open it in any text editor and type your mod name in it. Then you'll be able to launch your mod from the game's Mods list.
  2. Run ModStart.bat or EditorStart.bat from the Bin folder to open the editor or the mod.

When running a selected project, make sure the mod in project properties Debugging -> Command Arguments is set to your mod name instead of AMP2 (example: +game AMP2_Mod).

License

Just like Croteam's Serious Engine 1.10 source code, Serious Sam SDK is licensed under the GNU GPL v2 (see LICENSE file).

This SDK includes Croteam's Entity Class Compiler (Sources/Includes/Ecc.exe) that is used to compile entity source files (*.es) and is officially distributed with classic Serious Sam games. Its source code is included in Serious Engine 1.10.

Some of the code included with the SDK may not be licensed under the GNU GPL v2:

  • DirectX8 SDK (Headers & Libraries) (d3d8.h, d3d8caps.h and d3d8types.h located in Sources/Includes) by Microsoft

advancedmultiplayer2's People

Contributors

dreamycecil avatar

Stargazers

 avatar  avatar

Watchers

 avatar

advancedmultiplayer2's Issues

Only teleport players to PlayerActionMarkers of Run and RunAndStop types.

For proper singleplayer map support all players get teleported by the end of each PlayerActionMarker sequence. This is done so players don't get stuck anywhere and can continue playing after the cutscene is finished.

In order for it to work properly, instead of teleporting players to the last PlayerActionMarker that has been executed, they should be teleported to the last PlayerActionMarker of a type that moves the player (such as Run, RunAndStop and Teleport). Last such marker should be kept in a separate pointer and teleported to it by the end of the sequence.

Team-based game option.

An option to enable teamplay. The default setting is set to "No" which is just one team or in case of Deathmatch, one vs. everyone.

There could be up to 4 teams with specific skins and possible team-tags before the names.
Skins for each team can be selected via other options or a custom one via console command (the command will be a string - an AMC file name).

There could also be options for squad teams. Each player can either join someone else (2 or 3 people per squad) or play on their own (solo).

Teams are not very common for Cooperative mode, but they will enable a "Race" mode where each player/team gets a point by the end of the level if they get most kills/deal most damage to enemies.

Level patches don't apply after switching levels.

After going to a level that's supposed to apply custom patches (from LevelPatches folder), the patches don't work. The issue is possibly due to the patch being applied upon starting the game (perhaps in CGame::NewGame()), i.e. after loading the world for the first time.

But then after going to a level that's not supposed to have patches from the level that does, it still applies them (the class patches but not the dummy patches).

Basically the class patching remains consistent no matter what but should instead be updated each time the world is loaded.

Custom weapon models.

Load JSON configs of weapon models upon SWeaponStruct creation/loading into CPlayerWeapons. Set weapon models from the already parsed configs in SetCurrentWeaponModel().

Rework attachments for model configs.

Problem

Right now model configs in JSON format use AMC-styled attachment definitions:

"Attachment 0" : {
  "Model" : "Axis.mdl",
  "Texture" : "Vector.tex",
},
"Attachment 1" : {
  "Include" : "Attach.json",
},

This doesn't look very efficient and model configs should make use of the JSON format. To access data, you need to make use of either keys in their entirety or values under the keys.

Solution

New proposed format for attachments would look like an Attachments dictionary with entries under each attachment index:

"Attachments" : {
  "0" : {
    "Model" : "Axis.mdl",
    "Texture" : "Vector.tex",
  },

  "1" : {
    "Include" : "Attach.json",
  },
},

Pros and cons

This new solution will come with a few pros and very minor cons.

Pros:

  • Model attachments are strictly defined under the Attachments block.
  • Attachment indices as keys can be immediately converted into numbers for faster attachment access.
  • These same index keys can later be reworked to utilize attachment names from a predefined Attachment List file that can also be included in the config.
  • The block of attachments under index keys could also be replaced with an array, if needed, where each array entry will be a sequential attachment index. A null value could be used to skip some attachment.

Cons:

  • Conversion from AMC to JSON will be a bit slower. But there are only player skins in AMC format, so it doesn't matter.
  • Indices as key strings can look rather odd. But that's how generic JSON format looks like.

Animation sets for weapon configs.

There should be specific animation sets for each weapon that you can define in weapon configs.

Animation sets for viewmodels

These animation sets will contain animation indices under certain names and fixed animation lengths.

{
  // Animation for pulling the weapon out
  "Draw" : {
    "Anim" : 1, // Animation index
    "Time" : 0.5, // Animation length in seconds
  },
  
  // Cosmetic animation that plays after some time without an attack
  "Boring" : {
    "Anim" : [6, 7], // Array of multiple animations
    "Time" : 1.0, // All animations are 1 second long
  },
  
  // Fire/swing animation
  "Attack" : {
    "Anim" : [3, 4, 5], // One of the animation indices will be picked at random
    "Time" : [0.2, 0.25, 0.3], // Each length corresponds to an animation under the same index
  },
}

Animation sets for player item models

These can just have animation indices specified for the player model, since the viewmodels' animation lengths are used when animating both the viewmodels and the player body.

{
  "Draw"    : 2, // Animation for pulling out the weapon (e.g. BODY_ANIMATION_SHOTGUN_DRAW)
  "Holster" : 3, // Animation for putting the weapon away (e.g. BODY_ANIMATION_SHOTGUN_REDRAW)
  "Idle"    : 1, // Animation for just holding the weapon
  "Attack"  : 1, // This can match the "Idle" animation for no specific attack animation
}

Utilization in weapon configs

Then they can be added to weapon configs for all kinds of models:

  "AnimSets" : {
    "Main"    : "AnimSets\01_Knife.json", // Singular weapon
    "Dual"    : "AnimSets\01_Knife.json", // While dual wielding
    "MainAlt" : "AnimSets\01_Knife.json", // Singular weapon for alt fire
    "DualAlt" : "AnimSets\01_Knife.json", // While dual wielding for alt fire
    "Player" : "AnimSets\01_Knife_Player.json", // Player model animations
  },

Alive enemies counter is desynchronized.

Upon switching levels, enemies from the previous level are not cleared from the counter. Either that or they're not being counted upon joining the game (setting them to 0 and only counting new ones).

Fix singleplayer cutscenes.

The synchronization is still bad. The actions and current camera should probably be implemented in a global entity and then pulled from it by players.

  • All players but the first one should be teleported away from the world during any actions with the camera on (and teleported back to the first player when no active camera).
  • All players should be in the same spot each time PlayerActionMarker sequence is finished.
  • All players should have the same weapons by the end of the sequence if any new weapons have been received in a cutscene despite the shared weapons option.

Custom fire patterns for weapons.

Pre-load and compile scripts related to fire and fire patterns and store them in action lists of CWeaponStruct.

Execute in Fire() or AltFire() procedures within a wait() block that will wait for the returning event from the script (it will use a callback function with specific CPlayerWeapon entity ID as a reference that sends EFinishFiring or similar event to it).
To prevent weapons from being stuck in the procedure, check if the script has been executed correctly and release the weapon from the wait() block if not.

Alternatively have a pre-defined fire speed (in the weapon config) that can also have a random time variable.
Example:

"FireTime" : 1.0,
"FireTimeRND" : 0.2,
"AutoSuspendFire" : true,
This will set wait time between 1.0 and 1.2 in a special variable that's also passed by value into the script before execution.
If the script is still running when the waiting ends, its thread should be suspended automatically unless "AutoSuspendFire" or similar option is set to false.

Singleplayer cutscenes for one player.

Some cutscenes are not being played for multiple players and sometimes other players just get stuck in the beginning of the cutscene instead of being teleported away or proceeding with the first player.

ModelObject flagging for configs.

Add a map<string, CModelObject *> argument to the model config parsing that will set pointers to certain CModelObject under a specified string name.

Example:

{
  "Model" :   "Models/Weapons/Colt/Colt.mdl",
  "Texture" : "Models/Weapons/Hand.tex",
  "Flag" : "Hand",

  "Attachment 0" : {
    "Model" :   "Models/Weapons/Colt/ColtMain.mdl",
    "Texture" : "Models/Weapons/Colt/ColtMain.tex",
    "Flag" : "Colt",
  },
}

Will result in two entries in the map:
Hand = &CModelObject (main model)
Colt = &CModelObject::GetAttachmentModel(0)->amo_moModelObject (model under the first attachment)

Useful for animating different parts of the weapon/enemy just by grabbing the CModelObject pointer under the part name.

New powerups: Extra Ammo, Gunpowder Bag, Regeneration

New powerups to add to the token exchange list.

  • Extra Ammo: Every other shot doesn't consume ammunition.
  • Gunpowder Bag: Every bullet is explosive.
  • Regeneration: Add 5 health points per second (1 every 0.2 seconds).

Make DummyEnemy more customizable.

Custom model, sounds, attack animations etc.
Can be implemented via JSON configs which can also be used for map patching.

Example: map filename is MyMap.wld, the patch file is EnemyPatches/MyMap_1234.json. The number after the map name is for an entity ID of an enemy to affect (can be checked in Serious Editor).

Fix never ending prediction bugs related to custom weapons.

  • Third person flares appear on anyone other than the local client.
  • Crash upon selecting a new weapon while holding the fire button for clients with prediction.
  • Unsynchronized weapon rendering from the first person view due to not using variables from the original entity by the predictor.

Revamp multiple custom weapon models.

Problem

Right now there are 8 different weapon models for the first person view. Specifically:

  • Main model 1
  • Main model 2
  • Alt fire model 1
  • Alt fire model 2
  • Dual mode model 1
  • Dual mode model 2
  • Dual mode alt fire model 1
  • Dual mode alt fire model 2

This is way too many and it's overcomplicating the codebase.

Solution

Perhaps, instead of loading separate models from model configs, these configs could be unified.

So, the viewmodel class could contain two CModelObject (just like vanilla PlayerWeapons) and it will load models from such config:

{
  "Model1" : {
    <normal model config structure>
  },

  "Model2" : {
    <normal model config structure>
  },
}

Also these same viewmodel classes could contain the weapon animation set inside of them instead of existing separately as a part of CWeaponStruct.

Related issues

New gamemodes.

  • Survival - acts like a new gamemode (like Cooperative or Fragmatch) with waves of enemies. Typical survival mode.
  • Capture The Flag/Object - typical object-carrying mode with team markers and their flag/object on their own sides of the map.
  • Control Point/King of the Hill - same as CTF but with enemy points instead of objects or one point in the middle of the map. When one team reaches the point threshold, they win.
    Either time-based or point-based (time will be added for each team and points will first deduct from the team that stood on the point previously and then add to the current team).
  • Last Man/Team Standing - battle royale kind of mode. Dead players spectate the game until only one player/team is left alive. Can be played in certain amount of teams or solo/squad modes.
  • Special Delivery - same as CTF but with only one object that needs to be delivered by a team member to their special (or one global) zone to score a point.
  • Instagib/CTF Instagib - sniper rifle is the only weapon that kills enemies instantly. Can be a gamemode flag instead of a whole gamemode (to be able to play with it in CTF, Control Point etc.).

Need to implement gamemode-specific flags that will enable certain features within gamemodes that don't affect the gamemode itself (such as Instagib).

Crashes upon switching levels related to weapons.

For some weird reason all of a sudden weapons cannot access the player class by their pointer. It's just set to null, causing it to crash in SetCurrentWeaponModel() after changing levels. Also crashes on SetSoundOwner() because it can't retrieve the predicted entity for the same reason.

Weapon position multipliers for the first person view.

Add console commands for multiplying weapon position in the first person view for customization.
Something like amp_afWeaponPos (from 1 to 3) and amp_afWeaponRot (from 1 to 3), all of which are set to 1 by default. 0 would make weapons centered, -1 negate the position and so on.

For FOV it could be amp_fWeaponFOV with:
0 .. 1 = 20 .. original FOV
1 .. 2 = original FOV .. 120

Shared weapons setting doesn't work in demos.

For some reason shared weapons don't work in demos. They are perfectly fine in the game and seem to be perfectly synchronized but in demos when one player picks up the weapon, it still stays in place for others and they don't receive it.

Swap firing buttons if using dual weapons with mirrored weapons.

When holding two different weapons, each fire button affects its own weapon.
Primary fire affects the left weapon, while the secondary fire affects the right weapon. When weapons are mirrored, the firing is mirrored too.

Can be fixed by a single check in ctl_ComposeActionPacket that checks if the second weapon isn't WEAPON_NONE and swaps firing buttons if the mirroring is applied.

Only reset player's arsenal if weapon list is different on a new level.

After switching levels, player's weapons and ammo need to be reset in order to not lose weapons or ammo.
If weapon & ammo set for a new level is different, the arsenal should be recreated and not keep any of the old weapons/ammunition.
To do that PlayerInventory should keep a string to the used weapon set and compare it in CPlayerInventory::Copy() with the old one. If they match - copy the arsenal.

Use dummy player in cutscenes on singleplayer levels.

GlobalController should create its own Player class on SP maps that will be used for cutscenes.

When the cutscene is triggered, the dummy actor teleports to the spot of a player that triggered it and that dummy actor becomes a cutscene actor, copying the appearance of whoever triggered the cutscene, while real players wait in the dummy state until the cutscene is finished, where everyone teleports back to the dummy actor and it teleports away.

This is needed so the cutscenes can't be broken or softlocked if something happens to the actor (if they leave the server) in which case the cutscene can't be progressed any further.

Make custom HUD with customizable elements.

A refreshed HUD theme (enabled by default) with customizable colors and other adjustments.
Should fit new things better than the classic HUD and scaled properly (with screen anchors instead of position multiplication).

Player visibility.

Make an option to highlight players (make models brighter) so they're easier to spot.
Alternatively add a custom option that puts markers with player names and distances to players above them (for coop only).

Add custom entity patching during class reading.

Upon world start (from CGame::NewGame), the function for obtaining classes through .ecl files is patched and the replacement config for the current world is loaded.
If entity name in the .ecl exists in the config as a key, it gets replaced with its paired entity from the value.

  1. CGame::NewGame loads a world Level.wld.
  2. The LevelPatches/Entities/Level.json config is loaded.
  3. ECL obtaining function is replaced to the one that checks the name of an entity.
  4. The function looks up the key in the config and if it's there, gets a string with the new entity from AMP2.
  5. Creates and reads properties for the new entity instead.

Config example:

{
  "CNewEnemy" : "CDummyEnemy", // New class: CNewEnemy (CustomEnemiesMP.dll) -> CDummyEnemy (EntitiesMP.dll)
  "CTrigger2" : "CTrigger", // Same library (for mods): CTrigger2 (EntitiesMP.dll) -> CTrigger (EntitiesMP.dll)
  "CAmmoItem" : "CAmmoItem", // Same class (for entity packs): CAmmoItem (CustomItemsMP.dll) -> CAmmoItem (EntitiesMP.dll)
  "CModelHolder2" : "CModelHolder2", // Ignored if identical classes and libraries
}

Multiple flags per attachment in model configs.

Attachments in model configs can be assigned some name as a flag for easier access through code later without the need of hardcoding in paths to the model through a chain of attachments.

Right now there can only be one name assigned to them as a string. But if you could assign an array of strings to it, this attachment could be under multiple flags at once.

For example, if we have an attachment flagged like this:

"Attachment 1" : {
  "Flag" : ["a", "b"],
}

Then this exact same attachment model could be accessed using two different methods (example for PlayerWeapons.es):

CAttachmentModelObject *pamoA = GetModel("a", FALSE);
CAttachmentModelObject *pamoB = GetModel("b", FALSE);

Add more model types for weapons.

Problem

Right now you can only define two first person view weapon models (two different hands, like with Double Shotgun models) and one third person view models (holding a weapon item).

Solution

You need to be able to define a model for each kind of action.

Main viewmodel:

  • Main hand model (right now under "Model1").
  • Second hand model (right now under "Model2").
  • Main hand model for alt fire.
  • Second hand model for alt fire.

Viewmodel while dual wielding:

  • Main hand model.
  • Second hand model.
  • Main hand model for alt fire.
  • Second hand model for alt fire.

Player item model:

  • Item model (right now under "Model3").
  • Item model for alt fire.

Changes to weapon configs

Instead of having these keys in the weapon config:

  "Model1" : "Models1\05_DoubleShotgun.json",
  "Model2" : "Models1\05_DoubleShotgun_2.json",
  "Model3" : "Models3\05_DoubleShotgun.json",

  "Pos1" : [0.13, -0.21, -0.364, 2.0, 1.0, 0.0],
  "Pos3" : [0.0, -0.12, -0.3, 0.0, 0.0, 0.0],

They can be grouped under the Models block like this:

  "Models" : {
    "View" : {
      "Main1" : "Models1\05_DoubleShotgun.json",
      "Main2" : "Models1\05_DoubleShotgun_2.json",
      "Alt1"  : "Models1\05_DoubleShotgun.json",
      "Alt2"  : "Models1\05_DoubleShotgun_2.json",
      "Offset" : [0.13, -0.21, -0.364, 2.0, 1.0, 0.0],
    },
    
    "ViewDual" : {
      "Main1" : "Models1\05_DoubleShotgun.json",
      "Main2" : "Models1\05_DoubleShotgun_2.json",
      "Alt1"  : "Models1\05_DoubleShotgun.json",
      "Alt2"  : "Models1\05_DoubleShotgun_2.json",
      "Offset" : [0.13, -0.21, -0.364, 2.0, 1.0, 0.0],
    },
  
    "Item" : {
      "Main" : "Models3\05_DoubleShotgun.json",
      "Alt"  : "Models3\05_DoubleShotgun.json",
      "Offset" : [0.0, -0.12, -0.3, 0.0, 0.0, 0.0],
    },
  },

This should give enough freedom to customize how weapons look for any sort of situation.

Add a counter to SPlayerWeapon for telling how many times the weapon has been picked up.

It will act as a replacement for m_iAvailableWeapons for telling if the weapon exists or not.

0 - weapon doesn't exist.
1+ - has been picked up.
2+ - available as an extra weapon.

If it's less than 2 - it cannot be brought up as an extra weapon unless a special game option is turned on (allowing any weapon to be brought up at any time if at least one of it is available).

Scale option for model configs.

Currently it's impossible to resize the models within model configs. The "Scale" option will allow to do this.

It will contain size for each dimensional axis (X, Y, Z) like this:

{
  "Scale" : [1.0, 1.0, 1.0],
}

Due to how Serious Engine works, model scaling will only affect attached models if they are attached before resizing. So if the base model should be resized but not the attachments, the "Scale" option should be applied before adding any attachments.

Otherwise, to resize the whole model with its attachments, it should be done like this:

{
  "Model" : "Models\Enemies\Headman\Headman.mdl",

  "Attachment 0" : {
    ...
  },
  "Attachment 1" : {
    ...
  },

  // Will affect attachments that are added above as well
  "Scale" : [0.5, 0.5, 0.5],
}

No autosave after cutscenes.

New PlayerMarkers aren't created after cutscenes on singleplayer maps, making new/respawning players stuck in the beginning.

Support for The First Encounter maps.

Maps from The First Encounter are fully compatible with The Second Encounter. The only issues are that some entities have wrong states saved in them (due to different procedures in TFE SDK) and different sets of keys and weapons.

Entity states can be patched upon reading the map entities and if any of them happen to be patched, it means that it's a TFE map and the game should know that to later patch key types and weapon masks.

Keys and weapons are very troublesome to patch immediately upon reading entities because only a tiny percent of key and weapon types can be detected out of TSE bounds. So instead this is going to happen after the map loads and creates a GlobalController class, which will patch the remaining entities immediately.

Previous related commits:

User addon system.

There should be a system for supporting user-created addons (such as weapon sets).

All of the addons should be loaded in upon starting the mod and should be toggleable through a new special menu.

Concept

Addons can be anything that's not particularly used by the game or mod themselves, such as JSON configs (like current weapon sets). They can be of any type and depending on their type, they can be used in various specific-to-addon ways.

Then, these addons are a part of "addon packs", which are basically just configs with metadata about addons. These addon packs have a display name, an author and a specific version assigned to them, as well as dependencies and addons themselves.

Addon packs should look something like this:

{
  "Name" : "Default Weapon Set", // Addon display name
  "Author" : "Dreamy Cecil", // Addon author
  "Version" : 1.0, // Addon version
  
  // Dependencies as 32-bit hashes that can be unique to each addon pack and generated from their metadata
  "Dependincies" : ["AABBCCDD", "01234567"],
  
  // Specific groups of addons that this pack includes
  "Addons" : {
    // Right now the strings can just signify the folder name within "Configs/WeaponSets/" and "Configs/AmmoSets/")
    "WeaponSets" : ["Default"], // "Weapon Set" addons within this addon pack
  },
}

When specific addon is created upon loading in the pack (let's say, a "Default" weapon set), it will be added to a static map of addons of that specific type for later generic usage (such as verifying which weapon sets are available upon loading them for the game).

Special gibs and effects for blood types.

Valentine's Day type should have hearts instead of splashing blood.
Halloween gibs would be pumpkin pieces and candy.
Christmas gibs would be candy and Christmas decorations.

Birthday gibs would be pieces of a gift with fireworks.

Make new alt fire mode for Minigun.

It used to be dual Miniguns but since dual weapons are now a thing, this feature became obsolete and unused, should be replaced with something else.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.