That old HL mod of mine…

  • Creator
  • #6185


    It’s a mess. At least it’ll stay so, until I revive it one day.

    In 2015, I started working on my first (and only) Half-Life mod. I inconveniently called it Admer: The Game. Firstly, it wasn’t a game. It was a mod. Secondly, calling an entire mod after yourself is kinda self-centric. I eventually renamed it to An unknown game, which suited it a bit better. Still, it wasn’t a game. It was a mod. 😛

    I canceled it around 2016 because of the following:

    • I was an awful noob at programming.
      It was a time when I had just gotten into C++. My only prior programming experience in 2015 was QBasic. And even then it wasn’t much, although I was able to create a text game in QBasic. It was pretty fun.
      Essentially, I didn’t know about debugging, nor the basics of programming. My code wasn’t even mine – it was just pasted from tutorials I found on TWHL and Gamer-Lab RU. 70% of it wouldn’t compile, and 20% of what did compile ended up either not working in-game or crashing it.
    • I was losing motivation to work on the mod, because of the above. And as my mapping skills grew, I also started realising how terrible my mod’s maps were. I was too lazy to fix them or redo everything from scratch.
    • I was lazy. All my ideas were in my head, and I was too lazy to write them down. Fortunately, these ideas are still in my mind, just not in their original form. In fact, they’ve evolved for 3 years now.

    And then, one day, I took a look at the mod’s page on ModDB. I remembered the old statistics of the mod. It used to have 10s, 100s viewers a day, and now it has 0 or rarely 1. It used to be on the popular mods list for Half-Life, too! It was a serious achievement for me back then. So it made me feel sorry. It made me want revenge. Revenge against my back-then lack of knowledge and skills. I’ll fight back. I’ve been preparing for that for years. Various skills of mine improved since then: mapping, texturing, modeling, music production etc. but there was one skill that stagnated, because I didn’t pay enough attention to it.

    It was programming. In late 2017, I started panicking due to the fact that I knew I’d have Programming class the year after. So I wanted to prepare myself.

    I just needed a good start. Something to jumpstart my learning. And it happened one day. In December 2017, a guy came into our classroom, recording a promo video for the high school. We were having IT class, and our professor told us to pretend to be programming, because the guy was apparently recording a programming class. The others just pretended to be typing by touching the keyboard after they opened a source file. But me? Hah. I’ve always been an exception. I was actually writing code after I looked at some simple examples done by the older generations.

    When I returned home, I dug up a copy of VS 2010 Express so I don’t have to download it with my slow Internet, and I registered it, and I thought I’d make GMan killable.

    Caption: Returned to coding

    It was unbelievable for me. All that GMan was doing when attacked was this:
    pev->health = m_iMaxHealth / 2;

    The code is kinda self-explanatory. It just sets his health to 50% of his maximum health on every hit.

    I showed it to my then 7-year-old brother and asked “How cool is that?” He laughed in disbelief and asked me “But how?”
    I told him “Programming magic.”

    Either way, that was just the beginning. The big stuff was just behind the corner. But due to school, I couldn’t focus much on programming so I studied. And whoa. Nearing the end of summer of 2018 (was finishing my 1st year of HS), I started working on my Useless Suite. More on that in a separate thread. But it made me learn quite a lot.

    And then I soon tried going back to the Half-Life SDK, after Solokiller showed us folks, at the TWHL Discord, his own fork of the Half-Life SDK 2.4. It was modernised, player movement code in C translated to C++, made compatible with VS 2017, and a bit cleaned up. It sounded like a perfect baseplate for my mod’s code base.

    So I started working with it. After months of working on my Useless Suite’s Wireframe engine, I got myself familiarised with A LOT of the C++ language (at least relatively a lot), so I started recognising a lot of things. I actually understood the HL SDK code for the first time, at least whatever I was looking at. String handling was still a mystery to me (I’ll talk about it in a future post), and so were some things. But, all in all, I was able to create new entities by myself.

    I prototyped a function in AngelScript for Sven Co-op. It was called viewsway, and it basically modified the player’s view in real time. Essentially, you could achieve drunk view bobbing with it, or a rocking ship effect, or intense tumbling and rotations, whatever you need as long as your parameters are right. It worked, and then I decided to translate it to the Half-Life SDK as an entity: env_viewsway of the CViewSway class.

    And it worked. To me, it meant a new beginning, a new age. An age of learning what I’ve always wanted to learn. Programming is powerful.

    What I’m planning to do with this is finish the code base, add some dev assets for testing and maybe example maps and assets, and then to release it as a separate thing on ModDB. It’ll be sort of like Spirit Of Half-Life, but in a different flavour (and less crashing, I hope).

    I’ll put up a brief to-do list here:

    • fix the formulas for util_rotator’s secondary rotation option
    • add separate intensities for X, Y and Z for env_viewsway
    • story_choice and story_trigger
    • add util_cvar
    • implement FMOD

    It’s going to be huge. I’ll hopefully revise and improve all of my old code as I write code for new things. After all, I’m still learning. But, either way, it’s one hell of a learning experience.

    I’ll post some actual content about this in the next post, mainly a demonstration of the customisable HUD colours, and util_rotator.
Viewing 15 replies - 1 through 15 (of 15 total)
  • Author
  • #6379

    • topics: 2
    • replies: 11

    My dad’s been looking for a small vehicle ever since my family moved into our new house…..

    Hey Admer,where can I get that chair?

    AM to the PM,PM to the AM,funk.


    • topics: 47
    • replies: 347

    Are you driving a chair? 😀


    • topics: 3
    • replies: 62

    Well, I got a basic chair up and running (or rather sliding 😛 ):

    So, the controls work perfectly. Now I have to work on some physics. But first, some geometry. The chair has to rotate in a local axis, not the world axis, so I’ll use some transformations there and there (hmm, quaternions), and I’ll have to make the vehicle properly rotate depending on what ground it’s standing (although this will be dependent on the physics system later on).


    • topics: 3
    • replies: 62

    BLYAT, I scrapped 60% of the custom controls. Turns out GoldSrc will just overwrite a keybind if you bind a single key to two or more commands.
    bind q +adm_k1
    bind q +vehicle_unuse

    Q will be binded to adm_k1, then unbinded and binded to vehicle_unuse.
    So for vehicle control, I’ll resort to a “one configuration fits all” approach. WASD (movement keys) is accelerate, decelerate, steer left and right. Space (jump key) is handbrake, arrow keys will be up-down-lean left-lean right, reserved mostly for airplanes etc.

    So yeah. On the good side, this will mean it’ll be way easier for me to do control things, because there are no more 54 custom controls, just 21. 🙂


    • topics: 47
    • replies: 347

    @ Quake Community Website

    100%. It’s better that way. If I could go back and rename this site I would call it or … something like that. We got stuck with the quakeness, as this was intended to be a replacement for quakeone. However, I can do better than replace quakeone. Any developer or user with an interest in reading about development stuff should be able to participate here. Quake is one thing. I’m interested in 10’s of things and I don’t really care what the name of this site is, I’m not joining 10’s of communities to share my projects, ideas and inventions. Especially when this website has so many features and I have the power to add as many as I want.

    I seriously don’t give a fuck what people post about. I’m glad to have any kind of participation. Somebody here could start a poetry corner for all I care. The one problem I see with this site is it seems like everyone is off in their little corner doing their thing. I’d like to see more participation among members. A good example is my last post in Mr Burns OOP thread. I read what he wrote and it gave me questions. I found the answers to those questions and then I went back and shared them with him. I’m positive that at least some of that information is going to be helpful.

    My hope is that the new way I am allowing members to join will result in more members and maybe I can see that cross-participation happening. I’d like you guys to be able to come here and get 20 notifications that people are participating in your works, whatever those works may be. All of us get a lot of hits on our pages but, those hits are not translating to members. That’s probably my fault. I made a lot of changes today and hopefully participation will increase.

    @ijazz ~ start a dev blog – what would advantages be

    Yeah you should do that, and you can. The advantages are, eventually there will be more people and participation here and that will translate to participation in your blog. If you think about it, having the membership a little slim at the moment is perfect. This gives you a chance to get your stuff together and build up content so when participation does increase you have something to follow. Also, who knows, maybe your dev blog will be what helps increase the participation. Someone might love whatever you are doing and join just because of you. Or maybe even many someone’s. The way to grow this site is to grow the site. In other words, the more material, participation, ideas, etc… the more people will join. That leads to more participation, more content and more people … and more participation, more content and more people … and.. Ya see? There is a reverse effect to that as well. If you are doing something and people start taking an interest in it, you are going to work harder.

    I never stop trying to figure out ways to make things better around here. This means that, by default, you have me on your team trying to help make things better for you (for everyone). I am very open-minded to ideas. Being open-minded does not mean you will suggest something and it will happen. It does mean that I will hear your idea, honestly consider it and tell you yes, no or make it better and get back to me. All you have to do is realize that telling you no is not personal. I have 1000 terrible ideas a week and have to tell myself no. I’ve had terrible ideas, didn’t tell myself no and for some reason am still living it down over a year later. I even made a thread called terrible ideas and filled it with a terrible idea.


    • topics: 3
    • replies: 62

    Custom controls system a.k.a. ControlAPI (not really an API xD)

    There’s a structure called PEV. Or, Pointer to Entity Value, I believe. Every single entity has it. One of the keyvalues is called button. It’s an unsigned short int, meaning it’s 4 bytes or 16 bits big/long. Now, what that means is you can store 16 individual key holds. Move forward, backward, left, right, jump, attack, crouch etc. However, only 16 bits is not enough, and they’re all occupied as it is.

    So, I decided to do a workaround.

    gEngfuncs.pfnAddCommand("+adm_k1", IN_Adm1Down);
    gEngfuncs.pfnAddCommand("-adm_k1", IN_Adm1Up);
    gEngfuncs.pfnAddCommand("+adm_k2", IN_Adm2Down);
    gEngfuncs.pfnAddCommand("-adm_k2", IN_Adm2Up);
    gEngfuncs.pfnAddCommand("+sprint", IN_SprintDown);
    gEngfuncs.pfnAddCommand("-sprint", IN_SprintUp);

    In the input system initialisation, I tell the engine to add some commands, and link those commands to certain functions.

    AdmSrc Special code
    void IN_Adm1Up()
    void IN_Adm1Down()
    void IN_Adm2Up()
    void IN_Adm2Down()
    void IN_SprintUp()
    void IN_SprintDown()

    After that, I define those functions. EngineClientCmd issues a clientside command. Other commands use the KeyDown and KeyUp functions respectively, and my custom commands use EngineClientCmd. That’s the difference.

    Now, what happens next is a little bit ugly, but it works perfectly:

    // Use CMD_ARGV, CMD_ARGV, and CMD_ARGC to get pointers the character string command.
    void ClientCommand( edict_t *pEntity )
        const char *pcmd = CMD_ARGV(0);
        const char *pstr;
        // Is the client spawned yet?
        if ( !pEntity->pvPrivateData )
        entvars_t *pev = &pEntity->v;
        if ( FStrEq(pcmd, "say" ) )
            Host_Say( pEntity, 0 );
        else if (FStrEq(pcmd, "+key_adm_k1"))
            GetClassPtr((CBasePlayer *)pev)->SetKeyButton(adm_k1, true);
        else if (FStrEq(pcmd, "-key_adm_k1"))
            GetClassPtr((CBasePlayer *)pev)->SetKeyButton(adm_k1, false);

    I also defined two methods in the CBasePlayer class: SetKeyButton and GetKeyButton. 😉

    SetKeyButton and GetKeyButton basically access an array of bools. Each custom key has a bool of its own, to toggle states (pressed and not pressed).

    +adm1_k1 and +key_adm_k1 are different because the game would keep calling the same commands over and over again and the game would crash immediately. That’s one inconvenience of this system, but, I take it.

    And this is how any serverside entity will be able to accept custom commands from the player, including the player himself. This is how I enabled sprinting, and will eventually enable going prone.

    Keep in mind that EngineClientCmd (that is, a clientside call to the serverside ClientCommand) does NOT hold a key. It only does key strokes. This is why I did those bools, so whenever the player releases a button, a bool turns false, and vice-versa.

    Speaking of serverside entities that can take advantage of this ControlAPI…

    Vehicle system a.k.a. VehicleAPI

    This will perhaps be one of my greatest gifts to the Half-Life community, once it is finished. I don’t see why it couldn’t be ported to Quake either, though it’d require tweaking due to the engine differences.

    Here’s most of the header file:

    typedef enum InVehicleType_e
        InWalking = 0,
        InNPC, // Ahem, ON the NPC, unless it vored you
    } InVehicleType_t;
    typedef enum VehicleType_e
        VehicleChair = 0,
        VehicleCar, // automobiles, trucks
        VehicleBike, // bicycles, motorbikes
        VehiclePlane, // airplanes, jets
        VehicleHelicopter, // helicopters, drones
        VehicleShip, // spaceships, UFOs
        VehicleBoat, // boats, bath tubs, sleds
        VehicleNPC, // special, rideable NPCs. Think of horses, or no... GARGANTUAS >:D
        VehicleSpecialTest // chair that is like a car, needs no wheels
    } VehicleType;
    typedef enum VehicleSeatType_e
        Driver = 0,
    } VehicleSeatType;
    typedef enum RubberType_e
        Stock = 0,
    } RubberType;
    typedef enum VehicleDrive_e
        Drive_FWD = 0,
    } VehicleDrive;
    typedef struct
        int HorsePower;
        float MaxHealth;
        float GearRatios[9]; // Maximum of 7 gears + 1st neutral 0th reverse
        int Gears;
        float Efficiency;
        VehicleDrive Drive;
    } VehicleEngine;
    typedef struct Vehicleseat_s
        VehicleSeatType type;
        vec3_t pos;
        CBasePlayer *pSessilis; // Never thought you'd see Latin in the HL SDK, did ya?
        bool fExists;
        int iSitdex; // Cool name for a seat index 😉
        bool fCommands[16] =
            false, false, false, false, // acc, dec, lt, rt / shoot, shoot2, lt, rt
            false, false, false, false, // up, dn, llt, lrt
            false, false, false, false, // hdbk, cltc, jump, attack
            false, false, false, false // flashlight, unuse, startstop, seatswitch
    } VehicleSeat;
    typedef struct VehicleWheel_s
        vec3_t pos;
        float Traction;
        float Radius;
        float Wear; // One could also say damage
        float Width;
        RubberType type;
        bool fExists;
        string_t m_iszModel;
    } VehicleWheel;
    typedef struct VehicleBody_s
        vec3_t pos;
        float Mass;
        float Density;
        string_t m_iszModel;
    } VehicleBody_t;

    So yeah. It’s going to be pretty huge. I’ll try to keep it short:

    Vehicles can consist of 2 types of components: logical and physical.
    Logical components are engines and seats.
    Physical components are bodies and wheels.

    Engines contain performance info and stuff like that.
    Seats serve as pointers to players, and they’re the ones which actually listen to the player’s commands. There can be driver, passenger, gunner and outsider seats. Driver seats can control the vehicle, passenger seats let the player use weapons, gunner seats control the vehicle’s weapons (will be eventually implemented), and outsider seats, eh, dunno why I added them, because players will receive damage from bullets and stuff, no matter if they’re inside a vehicle or not. I might rename this one to DriverGunner and give it just that, an ability to be a driver and a gunner at the same time.

    Bodies and wheels contain a 3D model each, some physical info and whatnot. I’ll look into making the vehicles use different submodels depending on their health.

    GoldSrc physics, of course, are no good for this system. I’ll likely try something of my own, and it’s definitely going to take a while, simply because of the number of vehicle types. If I go that far though, I will also make a separate physics system, because why not.

    I recorded a video of the system in action:

    You cannot estimate how excited I became after I made it work. 😀


    • topics: 3
    • replies: 62

    Don’t let your failures (ESPECIALLY accidents) hinder you from progress, because they are part of progress by themselves. I once had to format my laptop’s HDD, I backed up all but my Far Cry maps, so I lost mp_verycold 0.99. Thankfully, I found 0.85 on MediaFire somewhere, so I am still able to work on it. The others… not so fortunate. My old HL mod from 2015 was also totally lost, i.e. the map sources, the videos, the screenshots, all but the source code and some textures and voice lines.

    You could make your own devblog group and post stuff. You could also join mine so you write stuff. “Development Shenanigans of Ijaaz and Admer” 😛

    Either way, it’s pretty cool. You have galleries, your own forum, BuddyDocs, BuddyDrive etc. OMG (not Oh My God, rather OneMadGypsy) encourages people to post stuff about their projects, which is good for a website like this, which remember, is not a Quake website, but a Quake community website, at least if I remember correctly.

    Edit: Oh, now I remember why you asked me something about OpFor viewmodels after that QuakeOne fiasco I caused. XD

    Edit 2: next up, I’ll post some progress on my vehicle API, or system, or base, whatever you wish to call it. UwU


    • topics: 2
    • replies: 11


    This reminds me of my own,1.5-year old,HL modding story.

    It began in 2016,when a friend of mine bought a copy of HL for me.I was excited,because I heard that it was an industry game-changer and wayy ahead of its time..I played the hell out of it,and (probably) for the first time actually enjoyed a game.
    Then,I got interested in modding.I downloaded all the modding stuff I could get.All the mods.Sounds.Images.Everything.It was around 31 GB  of mods and resources.

    I made a few mods,added a couple of weapons,changed HUD colors,etc.I wasn’t really a c++ pro at that time.I just saw a bunch of tutorials.Then,my school had some sort of competition,where a team of 3 could participate and win a prize.We had  to use Scratch and make something.

    My team formed at around that point.There were 2 guys,who also had HL.Let’s call then N and A.

    N and I were the guys without an programming experience whatsoever. I knew HTML and a small bit of CSS,while N was the go-to guy for anything like hard-drive failures,PC and laptop repairs,and any errors.

    A knew C++ and Python.He was the main programmer.N did the mapping and I did everything else(and a bit of weapons coding).

    It went well for a while.We made 2 maps,I messed around with weapons sounds and models and I got some CS1.6 weapons with a civilian guy’s hand and white sleeves.I got a dog from Quake into HL.A just did the rest.

    Fate had other plans.

    I was just tinkering with SoHL when my hard-drive failed.No big deal,just get a new one and get the backup from my friend.

    Turns out,I wasn’t the only one with a failed hard drive.

    When we finally got back our stuff,we lost 3 months of work.

    We lost interest.The project just sat there,no changes being made.I began to focus more on my studies

    On December 9,2017(my birthday) I was really depressed.A mood swing.I deleted every single one of my mod files.

    Soon I began to miss modding a game.The thrill,the feel,when you create something new.I missed that.Then I dug up an old copy of Quake my mom bought.Then I got more mods.Started modding.

    Should I create a dev blog for myself? What would the advantages be?

    AM to the PM,PM to the AM,funk.


    • topics: 3
    • replies: 62

    462 new lines of code. Trimmed some 750 lines of the original Get and SetKeyValue to 471, making the entire Get/SetKeyValue system about 933 lines (a bit more than that). It’s perfect.

    Now I can check for keyvalues that are not defined in the pev structure of the base entity class. I am so happy. 🙂

    Lip is defined as 20:

    So yeah. It works. Got nothing else to show right now, so I’m going to sleep. 😀

    The entire map looks like this now:

    As you can see, it’s got all my entities in it:

    • util_consoleprinter
    • util_rotator
    • env_viewsway
    • trigger_valueop
    • trigger_difficulty

    Next destination: define GetKeyValueCustom and SetKeyValueCustom for the CWorld class, and other entities that may require a custom Get/SetKV. And then I’ll add not easy, not medium and not hard to my trigger_difficulty, because there will be cases when you want to trigger something if the difficulty is NOT easy, or one of the other two. 😛

    And then, hopefully, FMOD to support more sound formats.


    • topics: 3
    • replies: 62

    I am using Visual Studio 2017. I used Visual Studio 6.0 when I first did C++, so I guess old habits die hard.


    • topics: 47
    • replies: 347

    There’s a lot of cool stuff here. Keep up the good work!

    I really like your syntax highlighting theme. What editor are you using? VSCode?

    @ and banning, jk

    It’s your group. You can do whatever you want. You can even ban me and I would respect that decision.


    • topics: 3
    • replies: 62

    I’ve tested the thingy, and it works perfectly. 😉

    As you can see, here I have 3 sprites. Red is Easy, green is Medium and blue is Hard. Depending on the difficulty, different sprites will be turned off. 😛

    And the entity that prints “Difficulty is: Easy” to the console is util_consoleprinter. It is exactly why I added it. It’s really useful for debugging your entity setups. 😀


    • topics: 3
    • replies: 62

    I always wondered why HL didn’t have an entity that triggers something depending on the difficulty. C’mon, it’s so simple to implement. But yeah, now it hopefully does. I’ll throw these methods out of the class though. I want it all nice and tidy.

    I’ve made a breakthrough. I went insane because CTriggerChangeValue from SOHL didn’t work, so I went and did my own complete implementation. I modified CBaseEntity to have 2 new methods, and that required some 760 lines of code + extra lines for each entity that uses custom keyvalues that are not defined in the PEV structure. (PEV -> Pointer to Entity keyValue)

    And it works. It does what it’s supposed to. It basically takes a keyvalue of an entity, and does stuff to it. Replacing, addition, subtraction, multiplication, division, trigonometry, modulo, logical operations (AND, NAND, <, >, >= and <= for now), and it can be configured to trigger another entity if the condition is true (for arithmetic operations it’s always true no matter what, keep in mind, and for logical operations it’s kinda obvious xd). It’s a damn powerful entity. You can even point it to a player and change their origin (oh lmao, that’s what trigger_teleport is for!) or ANYTHING you want. ANYTHING, I tell you. You can even crash the game with this if you want to.

    And now, the Efx API. 😀
    It’s my favourite!
    So basically, I discovered how messaging in Half-Life works and now I’m going to produce a parametric effects entity. Load a sprite that you want, configure how it moves and so on. Of course, this will need more tinkering and it’s all hardcoded for now.

    And here are the videos, to actually show what my stuff looks like:

    ^ Efx API test.

    ^ trigger_valueop demo.

    ^ custom HUD demo.


    • topics: 3
    • replies: 62

    Thanks. Lol.

    I’ve already gotten the hang of most of the things here, thanks to my curiosity. I’m yet to try BuddyDrive and Docs though. (and banning, JK)

    Sadly I don’t have the time to write that post which I planned to write (a demonstration of the customisable HUD colours, and util_rotator), but I might do it by the end of this week, hopefully with something more than that.


    • topics: 47
    • replies: 347

    Good stuff, bro. Keep it coming. It’s funny, when we were talking about you forming a group I had an image in my head of your banner being a composite of images … and sure enough that is exactly what you did. Even the overall collection of colors and shades matches what I was envisioning. It looks good.

    You didn’t copy my style. I don’t have a style. I made a dev blog … you made a dev blog. We have dev blogs. However, with the way you have yours configured I would like to suggest something. In your group description erase the part where you claim to be copying me and write something like this.

    “This group is open to the public but you must be a group member to comment. Clicking “join group” will automatically make you a member.”

    Also, just FYI, in “Manage” you can ban, promote and remove group members. Basically, you are a mini-admin of your group. Any choices you make regarding members of your group do not effect that persons overall site status. So, if somebody comes around and you ban them, they are just banned from your group. I believe the difference between ban and remove is: If you remove a member they can just click join group again, and the way you have it configured it would be like you did nothing. If you ban, I suspect that person will not even see the “join group” button. If you promote someone they can start threads in your forum and maybe some other things dependent on if you selected to have a group BuddyDrive and/or BuddyDocs.

Viewing 15 replies - 1 through 15 (of 15 total)

You must be logged in to reply to this topic.