Putting the 'role' back in role-playing games since 2002.
Donate to Codex
Good Old Games
  • Welcome to rpgcodex.net, a site dedicated to discussing computer based role-playing games in a free and open fashion. We're less strict than other forums, but please refer to the rules.

    "This message is awaiting moderator approval": All new users must pass through our moderation queue before they will be able to post normally. Until your account has "passed" your posts will only be visible to yourself (and moderators) until they are approved. Give us a week to get around to approving / deleting / ignoring your mundane opinion on crap before hassling us about it. Once you have passed the moderation period (think of it as a test), you will be able to post normally, just like all the other retards.

Which programming language did you choose and why?

Jasede

Arcane
Patron
Sad Loser
Joined
Jan 4, 2005
Messages
24,223
Insert Title Here RPG Wokedex Codex Year of the Donut I'm very into cock and ball torture
Yeah but sometimes you're stuck with Java 1.8 or 11. Records are a big improvement and personally, I like the lambdas as they can be more readable at times.
 
Last edited:

Hag

Savant
Patron
Joined
Nov 25, 2020
Messages
690
Location
Breizh
Codex Year of the Donut
Also, controversial opinion time (or, even more controversial opinion time): "Add Getters/Setters" features in editors are a mistake and you shouldn't use them as they encourage you to bloat your classes with needless functions that undermine your abstraction and essentially make your classes into data objects with direct access to their fields. In general you (for the most part) shouldn't be using getters and setters (or any amalgomation of them such as properties). Getters (and properties) I can understand, and I use them occasionally for getting data out of a class sometimes, but setters are almost always entirely useless. The interface to your class should be driven by it's functionality, not it's data. So you should tell a library to OrganizeBooks, not "SetOrganised" to true. Setters usually provide no opportunity for expansion, are horrible for encapsulation, and once you add a getter and a setter for a class member it may as well be a public variable, since it's the same thing.
Could be linked with how IT is taught. If you don't have quality lessons on how to leverage OOP strengths then the intuitive way is to cut short through the mandatory class boilerplating and add getters and setters everywhere so you can resume writing in pseudo C.
 

J1M

Arcane
Joined
May 14, 2008
Messages
13,238
Good god man, what a wall of verbal diarrhea! Just kidding, I kinda agree with much of it. I've always hated design patterns for example, not because they are always a bad idea (sometimes they are a great solution for some problems), but because they tend to put programmers (especially novice ones) into this mindset of "I gotta use all of these design patterns for every little shit", and yeah, that leads to horrific ugly-as-fuck needlessly obfuscated code. If you also think about writing code like writing literature (yes, I know they are different things), design patterns would be the loose equivalent of filling your prose with other people's paragraphs, which takes all the fun out of it. Design your own shit (unless you are stuck), it's a lot more fun. The great thing about doing it this way is as you gain more experience, you will independently arrive at some of the design patterns, and that will feel a lot better than just mindlessly trying to insert them into your code everywhere.

I actually wouldn't disagree about it being verbal diarreah. I just sort of threw everything out there in a rant style (since it was late) rather than taking the time to really structure everything, remove fluff sentences, and generally clean up my post. Which is ironic given that it's about clean code.

Design patterns can indeed be extremely good solutions. As can established algorithms. But as you rightly point out, whichever design pattern is popular at the time will be the "correct" way to program for a lot of people, until a new one becomes popular, then they forget the old one, and consider everything made with the old one to be "unmaintainable and out of date legacy code", because they never wrote good code to begin with. Nowhere is this more true than in the web space (I am convinced that 100% of web developers are completely incompetent if not outright frauds, but that's a rant for another day), where there seems to be a new "revolutionary" javascript framework every other week, and it always comes with some "new" design paradigm that just ends up being more boilerplate for no real benefit.

Comparing code to literature isn't that different after all. There's a reason for the old adage "good code should read like good prose".

And yeah, everyone is expected to make mistakes and write shitty code from time to time. Coding is hard, inherently, and nobody (even the experts) is particularly good at it. Humans are just not good at coding. But you can look for smells. One of them (which is usually considered a feature, not a smell) is when you have a IDelegateClassInstancerFactory or some other meaningless class names littering your codebase. If it's not a real concept with a real responsibility, ditch it. Most design patterns (and especially anti-patterns) will encourage the opposite. It's why I hate service-locator and singleton so much (seriously, NEVER use singletons. Not even in rare exceptions. They are literally completely useless in 100% of cases. There are no niches or special cases, just avoid them at all costs. They are kryptonite to good code. Even if people only skim this thread and don't bother learning anything, if they at least get the gist and as a result one time for one random project decide not to use a singleton one time, I will consider all of this worth it.)
I like your rants and I generally agree, but I do have to call out that in game development there are times when singletons make sense. For example, if it's a preferred pattern in the game engine you are using to have global access to something like a Settings or Game State object that is auto-loaded.
 

J1M

Arcane
Joined
May 14, 2008
Messages
13,238
Java was designed to be usable in the hands of morons.
...It's not a fun language to work with, because the base language is purely functional rather than elegant...
Java is neither functional nor elegant.

That said, I would take Java over Python any day of the week.
Yeah, selecting Java would allow you to substitute any JVM language. Kotlin has taken over Android development, for example.
 
Joined
Jan 5, 2021
Messages
122
I like your rants and I generally agree, but I do have to call out that in game development there are times when singletons make sense. For example, if it's a preferred pattern in the game engine you are using to have global access to something like a Settings or Game State object that is auto-loaded.

I fundamentally disagree.

While there may be times where you're FORCED to use a singleton (although I don't know of a single one), many engines like Unity don't actually encourage their use (and are better without them) despite the general community considering them necessary.

I am a Unity developer professionally so I will use a typical Unity case since it's what I know. Take for example a "game manager" singleton. Most games have one of these because it's just sort of "accepted" within the community that you need a game manager and that it's a "good idea" (I don't know where this came from but it's wrong). But even if we use the best possible singleton and make sure to try to use good design and make sure it only holds things related to direct game state - whether it's paused, if you're in a menu scene vs gameplay scene etc - and isn't some grab bag of random game data (I have seen people store player health in the game manager, sheesh), it's still better to use scriptableobject-based data containers and pass them to the relevant components as needed for various reasons, even for a singleplayer game where there will only ever be one player, and for things like game state. Using data objects and passing them to components (which can be made quite a bit easier and less tedious by using the "default script variables" feature in the Unity inspector) gives you a lot more flexibility and control, takes about as much effort as using the singleton, and isn't prone to horrible breakage like needing to completely save out and replace the player's inventory in a tutorial scene because their items are stored in the player manager. Now you just swap out the scriptableobject data container for that scene and the player is automatically using a different inventory with no code changes required. This can all be done through the inspector in a really nice way that game developers who might not be coders can understand and work with. It is both more transparent and more powerful than calling PlayerManager.Instance.Inventory in your code every time you want to use it.

For a real world example, in the game I am working on, I do not have a Game Manager singleton. I instead created a basic class for "game events", which live inside my project, and I can simply instantiate new versions of via Unity's create menu. One of those events handles pausing - when the player hits pause, it calls that event, and all listeners get notified. That's it. It does nothing else. I don't manage the game loop or timers or anything in there, they all handle themselves by listening for the event. I can drag any of those instantiated game events onto a script as if it was any other game object, and make scripts listen for generic game events and react, rather than needing to check for specific game state. Any script in my entire game can listen and react to any game event, so I can make certain things act or not act based on various conditions, including but not limited to the game pausing (I also have other events for things like player death, opening and closing the menu, etc). When I want, say, a torch to animate, and pause it's animation when the game is paused, I can do that by listening for the relevant pause event, which I simply drag in the inspector. This also means I can have torches animate or turn on and off or etc based on other events, like the player pressing a switch, with no script changes. I can easily add additional events to my project and any script that uses game events will be automatically compatible with them. They do not need to know about game state directly. This has saved a lot of headache and is a much better design than simply checking if the game is paused through some singleton to know if it should animate or not. This is also particularly nice because my game designer (who is not a programmer and has never written a line of code in his life) can simply change which event a given component listens for, so he can decide things like whether torches should still animate if the menu is open, without needing to talk to me at all. Just last week my sound designer added sound attenuation when the menu is open, which they did without writing any code - they simply hooked up a generic "set variable on event" script we made ages ago, linked it to the menu open and close events, set the variable to the global sound volume variable referenced by other objects (also an asset), and it worked. None of this would have been possible without code changes if we had to constantly reference singletons. This kind of design encourages modularity, adds a very healthy separation between components since they don't need to know about each other to function, and allows using simple and generic components that just listen for whatever game event you specify, and acting accordingly. Event-based (or message based) game design is always far more flexible and extensible than trying to constantly read and react to game state from singletons.

I do have something in most scenes called the "scene manager", but it's not a singleton. It's just a basic prefab that has a few scripts on it to listen for game events and act to do certain things (like activating or deactivating the game menu game object when the open and close menu events are called).

A lot of the design was inspired by this excellent talk on how to manage game state without singletons in Unity and frankly it delivers much better results than a "game manager" singleton ever could.

Even outside of Unity, it's usually worth it to make a proper system for giving classes access to the data they need (like through the factory pattern, although I don't particularly like that either) rather than using Singletons. It always saves you hassle in the long run.

Seriously, stop using Singletons. There are no good arguments for them. The supposed "you sometimes need a single state so they make sense" argument also falls flat, because you will only be better off by using something else and handling your "single instance" data like any other object instead - especially since, at least from my experience, data that "will only ever exist once", will often change during the design process to data that will, in fact, have multiple versions.

Obviously if there are game engines out there that give you literally no choice other than to use singletons, then grit your teeth use them as required, but I wouldn't consider that a legitimate use case or a reasonable justification for their use.
 
Last edited:
Joined
Jan 5, 2021
Messages
122
I think we generally agree. My comment was directed at those who are reading this thread and trying to learn while also encountering documentation like this from an engine creator: https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html
Cool, I have not used godot, thanks for this link, it's an interesting read.

It looks like they are requiring singletons for cross-scene data. In this case I still think the best approach would be to make a very minimal singleton which mainly exists to create and manage objects in a more proper fashion - creating things and passing in their dependencies via their constructors. Then, in the rest of your game code you do not reference that singleton at all. So it becomes more of a "class loader" or dependency injector, then gets out of the way. This should fulfill the requirements of the godot engine while allowing you to still write testable, maintainable, extensible code. Even if something needs to reference a singleton for whatever reason, the dependency injector could literally pass a reference to that singleton to relevant classes as if it was any other object, which allows mocking and all sorts of other benefits while still using the required singleton pattern.

I am not an expert on Java or where this pattern emerged, but it seems like Singletons were really designed to fit this sort of model. Be a single object that exists somewhere with a single state, but still allow regular objects to reference it as if it were a standard object that is passed to them, rather than using Singleton.Instance. This would give them an actual benefit over a static class. Unfortunately most people don't do this and always reference them "the easy way", which really defeats any sort of potential benefit. Even then, I think it's better to just never use them at all.
 
Last edited:

Hobknobling

Educated
Joined
Nov 16, 2021
Messages
120
I like your rants and I generally agree, but I do have to call out that in game development there are times when singletons make sense. For example, if it's a preferred pattern in the game engine you are using to have global access to something like a Settings or Game State object that is auto-loaded.

I am a Unity developer professionally so I will use a typical Unity case since it's what I know. Take for example a "game manager" singleton. Most games have one of these because it's just sort of "accepted" within the community that you need a game manager and that it's a "good idea" (I don't know where this came from but it's wrong).
http://gameprogrammingpatterns.com/singleton.html
Game Programming Patterns addresses this:

Many of the singleton classes I see in games are “managers” — those nebulous classes that exist just to babysit other objects. I’ve seen codebases where it seems like every class has a manager: Monster, MonsterManager, Particle, ParticleManager, Sound, SoundManager, ManagerManager. Sometimes, for variety, they’ll throw a “System” or “Engine” in there, but it’s still the same idea.

While caretaker classes are sometimes useful, often they just reflect unfamiliarity with OOP.

The author agrees with you:
The question remains, where should we use the real Singleton pattern? Honestly, I’ve never used the full Gang of Four implementation in a game. To ensure single instantiation, I usually simply use a static class. If that doesn’t work, I’ll use a static flag to check at runtime that only one instance of the class is constructed.
 

J1M

Arcane
Joined
May 14, 2008
Messages
13,238
Let's argue about something else, like how to implement aura buff effects that are conditional. For example: +1 fire damage to all goblins within 30 yards.

In a real-time game I think I would have a tick rate if 2 seconds or so and have the source apply a 2 second buff to nearby units. I assume there's a more clever way in a turn based game, but tracking onEnter and onExit seems messy and error prone vs. calculating it each turn.
 

JMab

Savant
Joined
Nov 12, 2013
Messages
177
Location
Melbourne, Australia
I agree that singletons lead to tight coupling which leads to future design pain and difficult refactoring.

I use Unity with the Extenject dependency injection framework which is an elegant alternative to singletons. You get the best bits of singletons - only one instance, initialized exactly when you need it, accessible to any other service you use (you get to be explicit), etc. without the tight coupling.

One way to avoid the tight coupling is to inject interfaces rather than concrete classes, so you can swap out services for testing (e.g. replace the PlayerInput service with an AIInput service to test repeatable PC commands).

The other great thing that Extenject offers is also mentioned above - a message bus. They call it signals. So you signal that the main menu has opened and the input service shows the mouse cursor, the PlayerCharacter services disables the player input, the GameService pauses the game time, the WorldService pauses the world time, etc. without having any awareness of the main menu itself (or vice-versa).

Using the framework properly kind of forces good, loosely-coupled, service-oriented game design.
 

JMab

Savant
Joined
Nov 12, 2013
Messages
177
Location
Melbourne, Australia
If we’re looking for other things to argue about, I’d be interested to know what any devs are doing with character classes.

I started with a simple inheritance hierarchy, Character -> HumanoidCharacter -> PlayerCharacter or NPCHumanoid, but already I’m getting some headaches and I think it’s because I’ve violated the prefer composition over inheritance principle. Thinking of just having a Character class with a Controller component that can be AI or PC and an Avatar component that can be a customizable humanoid or any skinned mesh. Actually I’m almost convinced that’s the right approach but I’m sure there are a few alternatives.
 
Joined
Jan 5, 2021
Messages
122
I use Unity with the Extenject dependency injection framework which is an elegant alternative to singletons. You get the best bits of singletons - only one instance, initialized exactly when you need it, accessible to any other service you use (you get to be explicit), etc. without the tight coupling.
I don't really see much point in using ANY dependency injection system in Unity since it already has a pretty good one built-in, the inspector. Almost all of your game logic can (and very much should be!) represented as interconnections between GameObjects and ScriptableObjects. You don't get the "create on demand" functionality, but your objects should be so small, modular and specific as to not warrant it anyway. In the worst case, you can write your own simple system that uses ScriptableObject.CreateInstance or GameObject.Instantiate() from some core place, with you still using references in the inspector.

This has a number of significant benefits. The main one being that your artists and game designers can link game systems together in a graphical way without having to write a bunch of extra code to draw a UI for your dependency injection systems.

One way to avoid the tight coupling is to inject interfaces rather than concrete classes, so you can swap out services for testing (e.g. replace the PlayerInput service with an AIInput service to test repeatable PC commands).
From my experience in both business programming and game developments, interfaces in Service-oriented systems are largely a waste of time. The only benefit you get is that you can stub them, but services are usually so specific that you won't ever polymorph any other version in your actual application code. I find this to be one of the many core problems with the service-oriented design pattern - it largely violates OO by moving functionality into separate services (which usually end up as god classes, at least they have in every project I have worked on in a professional capacity), and keep most of the core objects as POD objects. In general, POD objects should be avoided - you're basically using a struct at that point and calling free functions exactly the same way you would in a traditional procedural program, it just LOOKS like an OO approach because you wrap it all in classes. The service oriented approach LOOKS like a good design on the surface because you're abstracting away all your functionality which looks correct. It's usually much better to just make simple, generic classes that do a simple job and then pass objects to each other through the constructors (or in the case of Unity, through serialized private fields) and call it done, and avoid any amalgamation of any service pattern entirely. People tend to go too far the other way at times, which more often than not results in each of the business objects being a god class. That's also wrong, and I can see how in that scenario the service pattern would look appealing, but it's really a lie - it's just procedural programming again. The correct approach is to decompose your infrastructure into small, interconnected and generic objects, and pass them around. If what you use to pass them around is called a "service", that's fine, but it shouldn't be doing any of the core business logic. This allows a much greater degree of control over polymorphism, abstraction, code reuse, and generally better quality software all around. There's no point having an IDatabaseService since everything is always going to talk to the core database in the same way anyway, and if it has functions like AddUserInfoToDatabase(User u), then your functionality is so specific that inheritance is worthless. This is the usual problem I find with services. Instead, just make a generic DataSource which you can pass to all your business objects, so you can extend it with DatabaseSource etc and gain back polymorphism (and gain the ability to later add support for, say, text file data sources for free). It may seem like a pretty minor change but at that point you have abandoned the service pattern entirely.

The other great thing that Extenject offers is also mentioned above - a message bus. They call it signals. So you signal that the main menu has opened and the input service shows the mouse cursor, the PlayerCharacter services disables the player input, the GameService pauses the game time, the WorldService pauses the world time, etc. without having any awareness of the main menu itself (or vice-versa).

Using the framework properly kind of forces good, loosely-coupled, service-oriented game design.
This can be done quite a bit better using GameEvent and Variable scriptable objects, since they exist globally. They can easily be dragged and dropped in the inspector too, allowing your artists to hook up UI to whatever events they want (like adding a boss health bar for the BossHP variable which is set by the generic "Unit Health" component on the boss (with the same component on the player setting the PlayerHP variable).

A similar system is documented here: https://www.youtube.com/watch?v=raQ3iHhE_Kk

There really is no need to use Singletons, and there's no reason you should need any sort of dependency injection framework either - Unity already does it for you, and more often than not, in a much better and more inspector-integrated way than many third-party code-driven solutions. I would seriously look into using a scriptable object architecture instead.

If we’re looking for other things to argue about, I’d be interested to know what any devs are doing with character classes.

I started with a simple inheritance hierarchy, Character -> HumanoidCharacter -> PlayerCharacter or NPCHumanoid, but already I’m getting some headaches and I think it’s because I’ve violated the prefer composition over inheritance principle. Thinking of just having a Character class with a Controller component that can be AI or PC and an Avatar component that can be a customizable humanoid or any skinned mesh. Actually I’m almost convinced that’s the right approach but I’m sure there are a few alternatives.

I don't have a "character". I instead have a Unity GameObject called "Humanoid" with a "Walker", "Inventory", "Health System" and a few other components. These components are generic. For example, the walker takes an input (a scriptableobject called WalkerInput), which is usually controlled by the AI, but for the player character (which is just another humanoid), the input to their walker is a ControllerInput, which inherits from WalkerInput and sends events to the walker based on controller inputs. The player is set up as a prefab variant with the right inputs already set in the inspector. Other object types (such as container) simply reuse the "Inventory" component. Things like explosive boxes can use both "Inventory" and "Health system", etc.

It's effectively a "composition over inheritance" system, but in a Unity flavor using components rather than instantiating (or passing in) classes via a constructor.
 
Last edited:
Joined
Dec 17, 2013
Messages
3,770
My 2 cents:

I don't want to say that "best practices" shit like unit testing, test driven development, agile development, SCRUM meetings, coding to interfaces, design patterns, etc are bad, because the truth is I don't know. But I have a suspicion that nobody else knows either. Some fairly smart people came up with these things because they thought they might improve development, and many others adopted them because books were written, and it kinda makes sense when you read it. But as with all complex systems (which software definitely is), it's somewhere between extremely difficult to impossible to really understand how anything truly works. And smartest people can routinely be wrong about everything.

From my personal experience, I've been part of relatively amateur teams that cranked out valuable functional code at ridiculous speeds while being completely ignorant of most of these best practices, simply due to hard work and individual talents of the participants. I've also been part of highly elite teams that spent years rewriting and redesigning systems to "nail it" just right according to all of these best practices, in the process hurting the business they worked for. So ... life is complicated.
 
Joined
Dec 17, 2013
Messages
3,770
P.S. I think the main reason most OOP projects use massive services is because it makes it easier to write code up front. With proper OOP, you have to think about which object to put which logic into and how these objects will interact with each other, which for complex business domains is not that simple.

By putting all the logic into these huge service classes, you can avoid all this work up front and just have a single class with all the logic for some particular part of your software. So it makes things a lot easier in the beginning.

Of course over time, those service classes inevitably balloon into unholy unreadable walls of code, which become so difficult to work with that developers start breaking them down into smaller "sub-service" classes. So in a way, it's almost like you are working your way backwards toward proper OOP, as these smaller service classes start approaching single class territory.
 

DakaSha

Arcane
Joined
Dec 4, 2010
Messages
4,734
who the fuck "chooses" a programming language , anyways
 

BanEvader

Educated
Shitposter
Joined
Nov 8, 2021
Messages
126
Y'all niggas shit's all fucked up.
Forget coding.
Stop staring at pixels.
Go get laid.
Learn an actual skill.
Build a fucking cabin in the forest and proceed to create improvised explosive devices that you'll mail to various random people that sustain and propagate industrial society.
And above all else, stop playing vidya.
 

Absinthe

Arcane
Joined
Jan 6, 2012
Messages
3,890
Let's argue about something else, like how to implement aura buff effects that are conditional. For example: +1 fire damage to all goblins within 30 yards.

In a real-time game I think I would have a tick rate if 2 seconds or so and have the source apply a 2 second buff to nearby units. I assume there's a more clever way in a turn based game, but tracking onEnter and onExit seems messy and error prone vs. calculating it each turn.
Tick rate is the easy and reliable solution but if your engine is good and your own engine code is good, you could also have all forms of unit movement automatically check for positional effects and whatnot. Implementing this in a reliable and efficient way can get complex fast, but if you have the skills it probably produces best results. If this is Unity shit, I recommend tick rate, easy. The only major tick rate optimization I would recommend is having a standard heartbeat for these kinds of things so you don't launch thousands of separate tick rates for every effect. The other bit of advice I have is to keep in mind how you intend to do multiplayer. Because if you want to do multiplayer, odds are you're better off just building your engine around the needs of multiplayer.
 
Last edited:

J1M

Arcane
Joined
May 14, 2008
Messages
13,238
Let's argue about something else, like how to implement aura buff effects that are conditional. For example: +1 fire damage to all goblins within 30 yards.

In a real-time game I think I would have a tick rate if 2 seconds or so and have the source apply a 2 second buff to nearby units. I assume there's a more clever way in a turn based game, but tracking onEnter and onExit seems messy and error prone vs. calculating it each turn.
Tick rate is the easy and reliable solution but if your engine is good and your engine code is good, you could also have all forms of unit movement automatically check for positional effects and whatnot. Implementing this in a reliable and efficient way can get complex fast, but if you are good at it it probably produces best results. If this is Unity shit, I recommend tick rate, easy. The only major tick rate optimization I would recommend is having a standard heartbeat for these kinds of things so you don't launch thousands of separate tick rates for every effect. The other bit of advice I have is to keep in mind how you intend to do multiplayer. Because if you want to do multiplayer, odds are you're better off just building your engine around the needs of multiplayer.
I decided to create an AuraManager that basically asks each aura to provide a list of characters it applies to and then calls the aura's apply function for each character.

These effects are wiped out as the first step the next time the aura calculation is started. Given how fast it is, I am currently just running it each time a segment of a turn is resolved.

Implementation detail: I gave each aura a priority level so they are applied in a deterministic order. For example, apply flat +2 modifiers before percentage-based ones.
 
Joined
Jan 5, 2021
Messages
122
Let's argue about something else, like how to implement aura buff effects that are conditional. For example: +1 fire damage to all goblins within 30 yards.

In a real-time game I think I would have a tick rate if 2 seconds or so and have the source apply a 2 second buff to nearby units. I assume there's a more clever way in a turn based game, but tracking onEnter and onExit seems messy and error prone vs. calculating it each turn.
Tick rate is the easy and reliable solution but if your engine is good and your engine code is good, you could also have all forms of unit movement automatically check for positional effects and whatnot. Implementing this in a reliable and efficient way can get complex fast, but if you are good at it it probably produces best results. If this is Unity shit, I recommend tick rate, easy. The only major tick rate optimization I would recommend is having a standard heartbeat for these kinds of things so you don't launch thousands of separate tick rates for every effect. The other bit of advice I have is to keep in mind how you intend to do multiplayer. Because if you want to do multiplayer, odds are you're better off just building your engine around the needs of multiplayer.
I decided to create an AuraManager that basically asks each aura to provide a list of characters it applies to and then calls the aura's apply function for each character.

These effects are wiped out as the first step the next time the aura calculation is started. Given how fast it is, I am currently just running it each time a segment of a turn is resolved.

Implementation detail: I gave each aura a priority level so they are applied in a deterministic order. For example, apply flat +2 modifiers before percentage-based ones.
Look into the way the Dark engine does stims. It's a very clever way to deal with auras, on-hit effects, etc.

the TL;DR is basically that when something "affects" something, it's passed a stim (which in your case would be an implementation of some interface) and each entity can have it's own implementation of how to handle that particular stim. Stims themselves do nothing, they are just identifiers for "you are affected by this now"
 

J1M

Arcane
Joined
May 14, 2008
Messages
13,238
Sounds overly complicated and a bit like the first idea I had, but those systems are prone to the kind of bugs the Neverwinter Nights engine had. (Sometimes a buff doesn't drop off correctly, so you could stack it indefinitely until a map transition by swapping cloaks or whatever.)
 
Joined
Jan 5, 2021
Messages
122
Sounds overly complicated and a bit like the first idea I had, but those systems are prone to the kind of bugs the Neverwinter Nights engine had. (Sometimes a buff doesn't drop off correctly, so you could stack it indefinitely until a map transition by swapping cloaks or whatever.)
The problems in NWN happen because the effects would maintain their current state until told to change. This meant if they missed the change message for whatever reason, they would be stuck forever.

The thing with stims is, each has their own update loop (technically each thing affected by a stim has the update loop, but it's the same concept), so these issues shouldn't happen because the stim will destroy itself the moment it's conditions are no longer true.
 
Joined
Jan 5, 2021
Messages
122
Only c and c++ are good languages.
Wrong.

C and C++ are both terrible languages for very different reasons.

But all programming languages suck to some degree.

Ways in which C sucks:
- The language is so barebones that basic types like bool weren't added until 2003, making a lot of older code fundamentally incompatible with the new stuff, so nobody uses it. not having real bools, generics, real constants or real references causes a lot of unnecessary issues, reduces type checking, and generally makes C an absolute minefield to work with. Why have a nice, well-defined generic delegate class (or functor<>, in the case of C++), when you could just use void* and get no help from your compiler at all!
- Manual includes results in a lot of headache and extra work, which people supplement by using tools like cmake. Cmake is absolute cancer and nobody should use it, but your alternative is either complex makefiles (which are impossible to maintain), or a severe lack of encapsulation.
- Object Orientation is impossible. Some people see this as a feature, but the reality is there are some applications where inheritence is a very good approach (eg component widgets for a GUI). C programmers claims inheritence is possible, which is true, but it involves horrible individual memory hacks, things like purposely writing over the end of a struct to fill a different struct with the same overall layout plus additional fields. None of this is supported by the language and is very prone to breakage.
- The language is so low level that doing any sort of high-level logic is impossible, even in places where appropriate. A better made language would pass around references and let you work on them. C is likely to give you a void*, return an integer error code, and overall require you to know the ins-and-outs of every specific details of every object you're working with. This contributes to making abstraction harder, if not impossible, and is why C programmers can never quite get into the "move customer to new manager" mindset rather than "assign Customer* pointer to a manager struct's 'employees' array and make sure you check the error_flag variable to make sure it's not -1". It's madness. Low level implementation details are constantly getting in the way of high-level business logic, and vice versa.

Ways in which C++ sucks:
- It's effectively 3 languages in one, with 2 of those languages being deprecated. Do I use int i = 3, or do I use int i { 3 }. Don't use auto_ptr, it's deprecated. But books still mention it. As do guides. Many codebases rely on it. C++ has a lot of deprecated features that are still present and that you shouldn't use, but which even a well-read developer could miss because of how commonplace and accepted they are. This is largely caused by the next problem...
- The standard library is a complete mess. This is largely because it was implemented as a set of free functions working on iterators, rather than being a set of abstract classes which can be extended to implement things like lists. As a result, application code isn't tied to interfaces, it's tied directly to library functions. This makes it impossible for the C++ team to remove old cruft or update any library functions, because code relies on their existing functionality. Even if this was still impossible with an interface-based approach, it would be easy for people to simply swap out one implementation for another in their codebase if they are passing the interfaces to their classes/functions as needed. The C# standard library works like this and it's way better to use as a result.
- C++ lacks language niceties from other languages (like properties) because they are "unsafe", and yet I can do plenty of unsafe things like redefine the = operator to cause a memory leak. The language lets you do some really powerful and dangerous stuff, which is good, but the standardisation team seems to have missed the memo and is refusing to add features that are "too dangerous" as a result. As a result, C++ is both very easy to break your codebase with, and yet also doesn't have the language niceties required to actually abstract things nicely. It's the worst of both worlds.

Overall, I still really like C++, way more than C, and I use C# for my day job and it also has plenty of problems (the implementation of "interfaces" rather than using abstract base classes or allowing multiple inheritence being one of it's biggest issues), but the languages are beyond broken in many ways,

Ideally, I would like someone to create C+, which is basically

- C style syntax, plus classes, templates, properties, and some other nice OO and C++ features
- None of the C++ bloat
- Proper imports, rather than includes.
- A well structured standard library based on abstract classes
- Full Multiple Inheritence support, no stinkin' interfaces!
- No need to be backwards compatible, a clean slate, so we can get rid of the cruft from both C (BOOL, #define, etc) and C++ (auto_ptr, etc)
- Separate operators for integer and float division, since that's a pet peeve of mine.
 
Last edited:

J1M

Arcane
Joined
May 14, 2008
Messages
13,238
I would be interested to know your thoughts on Go and Carbon, since they both seem like an attempt at that.

There's also Jai, which is basically C++ if it was designed with games as the primary consideration.
 
Joined
Jan 14, 2018
Messages
45,716
Codex Year of the Donut
C++ is a fine language, the issue is the standard library is garbage other than a handful of things. And they keep putting more crap in it nobody wanted or asked for other than people on the standards committee.
Did you ask for <ranges>, one of the most overdesigned and retarded library additions I've ever seen? No? Too bad, it makes EVERYONE(yes, really) compile programs slower because it infects nearly every header in the standard library. <regex> is unusable crap, <filesystem> is massive because they insist upon making everything header-only(another trash design decision pushed by retards).
Tried to use <random> lately? Why is it so fucking hard to just generate a random number?

What a fucking shitheap. I can't remember the last library addition after unique_ptr I gave two shits about. The few times they do add something that may SEEM decent it ends up being a shit implementation due to endless compromises so you're not going to use it anyways. It's no wonder things like abseil and folly exist with how garbage the standard library is.
 

As an Amazon Associate, rpgcodex.net earns from qualifying purchases.
Top Bottom