Creating active monsters with HP and attack?

I've just started using Quest quite recently, and I want to create an RPG-like game so badly, with monsters that can attack the player and have health. Problem is, I don't really have much knowledge about coding and all. I've been visiting lots of websites just to find myself being even more puzzled with their novel-long explanation.

Please help meee!
I will even post my unfinished game if that's necessary!

Also, I don't really understand how you express HP and stats such as agility in a text-based game. Tried everything I can but I'm still lost.


If no one helps you in the next 12-hrs, I can post something that should help. Just a warning, I tend to do things a little unorthodoxed. They still work, but it’s in a way that my brain can manage. :)


Io

MY TIME TO SHINE!

Bear with me, this'll look long and scary but I promise I'll make it as understandable as I can.

First thing to know, is that coding is like those school assignments you might've gotten as a child, asking you to write out the exact instructions for some simple task like making a sandwich - the computer will do EXACTLY what you tell it to do, but not necessarily what you WANT it to do.

There's a lot of libraries out there with pre-made RPG mechanics. But then you have to go in and get used to the code that someone ELSE made. Given that there's a bajillion ways to do the same thing in programming, this is not something I recommend.

Instead, I find it better to build up the 'skeleton' of your game on your own. Which is something I did with my two games: I needed a VERY robust battle system, where I could have team fights of 4v4 or 2v3 or whatever I needed, buffs, ability cooldowns, and more, all on the fly.

I won't explain exactly everything I did, because that leads you to the same problem as before, but I WILL give you the highlight: I won't give you the car but I will give you the tools I used to build it.

Stats in Text: You can print stats. Say you have an object called EnemyOrc1. EnemyOrc1 has the attribute (You can give stuff custom attributes in the 'attributes' tab, go figure) Health. The game's code calls this attribute 'EnemyOrc1.Health', and let's say it's equal to 50. There's also EnemyOrc1.MaxHealth=100. You're fighting a grizzled, wounded soldier.

In a piece of text, you can write:

{EnemyOrc1.Health}/{EnemyOrc1.MaxHealth} Health

Someone plays it, gets to that section, and sees:

50/100 Health

In most cases you'll want a LOT of attributes controlling the enemy, but the exact ones depend on your game. For instance, my sci-fi game has 'IsMechanical' as a boolean (True/False) attribute for the purpose of robotic enemies, but that'll make little sense if you're in Middle Earth!

Some probably useful ones for you:
Health
MaxHealth
Mana
MaxMana
Active (Has this enemy been defeated?)
FriendOrFoe

CHANGE SCRIPTS
So you've made EnemyOrc1, given him EnemyOrc1.Health and EnemyOrc1.MaxHealth and such. You have a command where the player enters 'Hit orc', and the game executes:

EnemyOrc1.Health = EnemyOrc1.Health - Player.AttackDamage
msg("You hit the orc! {Player.AttackDamage} damage!"

and the player sees:

You hit the orc! 85 damage!

And now the Orc is at -35 Health.

But how do you actually, you know, make him fall over dead? It'd be pretty tedious to make every single way to damage every single enemy have to INDIVIDUALLY run the code:

if (WhateverEnemy.Health<=0){
WhateverEnemy.Active=False
}

, right? For hitting EnemyOrc1 with a sword, with a mace, with a magic potion, hitting EnemyOrc2 with a sword, with a mace... LUCKILY YOU DON'T HAVE TO!

Go to EnemyOrc1's attribute tab. You see the + sign to make a new attribute, the - sign to delete an existing attribute? But what's this 'boxed +' next to it? That makes a changescript.

Select EnemyOrc1's Health attribute. Press boxed-plus and you'll create a new attribute called changedHealth.

This is basically a bit of mini-code, that will fire WHENEVER EnemyOrc1's Health changes. Just slot in the code:

if (this.Health<=0){
this.Active=False
}

'this', of course, being a way to tell Quest 'Hey, dummy, specifically THIS object!' without needing to write the name.

You can do this to whatever EnemyOrc2 EnemyDragon3 AllyFairy2 you want.

This leads into:

$#@%ing Functions, How do they work?

Are you writing a piece of code over and over and over, and are sick of doing so? Do you wish there was a way to just set it aside and tell Quest 'Yeah, and just run that piece, no I'm not typing it out again'?

LUCKILY THERE IS! On the left side, scroll all the way down to Functions, select it, and make a new one. Call it something creative, something snazzy, like TestFunction.

Something new opens up, and it looks pretty overwhelming! Return type?! Parameters?! What are these?

Not important, is what they are. The import bit is the Script bit, where you can type in whatever code you want. Like:

msg("This is my test function")
msg("It's printing a bunch of nonsense for the player")
msg("It'll do this every time I 'call' the function")
msg("Which is programmer talk for 'Hey Quest, do that code thing, no I won't type it out again, yeah the one I called TestFunction, do it'")

Now, go to somewhere in your main game's scripts and just Call Function 'TestFunction', leave the Parameters empty.

Run the game, and see how it'll print that out whenever you call TestFunction. You can put more stuff into that. Me personally, I have a bunch of functions for my game, like ReceiveDamage to reduce someone's incoming damage by how much armor they have, or MainTurnHandler to decide who's turn it is, and to check if the player's won, lost, or still fighting at all before having EnemyMook53 take their turn. I even had a StatUpdate where I set someone's MaxHealth to their BaseMaxHealth and modified it with buffs/debuffs and blah blah blah.

You just make whatever functions you want.

ADVANCED Functions

Remember those Parameters and Return types? Well they're useful in some cases. I'll skip Return types because you really shouldn't ever need them - I sure as hell didn't.

Parameters is basically a 'fill in the blank' for the function. Let's make a new function 'TestAdvancedFunction' - function totally doesn't seem like a word anymore. Give it 1 Parameter. One single Parameter. Call it 'DudeName'.

And have the script be:

msg(DudeName+" is the parameter I passed to the function")
msg("There weren't any quotations around DudeName because I used expression mode for these prints rather than text")
msg("And doing that basically puts it in code-view and let's you get funky")

Now go somewhere in your game and call function TestAdvancedFunction. But now press the button and enter, with quotations, "Bill".

In the game, you'll see:

Bill is the parameter I passed to the function
blah blah other stuff

You can do a bunch of crazy stuff, like have function SendHealing with Parameters "Target" and "HealAmount" do:

Target.Health = Target.Health+HealAmount

And just call that with the target's code-name and the number for healing whenever you want to heal anyone. Functions can even call other functions, so you can have 'SendHealing' call another function called 'ReceiveHealing' where, depending on who Target is, they say "Thanks for the healing, pal!" or "Thanks for the healing, minion!" Just be careful not to make an infinite loop...

WARNING: Quest is very fickle. If you CALL a function, and give it more parameters than it has, or fewer than it has, the game will absolutely go ballistic.

But I don't WANNA make a separate object for EnemyOrc12 and FinalBossMook32! There has to be a better way!

Luckily there is! And this is where things start to get weird.

There is, in the game, a block of code called Clone Object, and a more useful one called Clone Object and Move. This does exactly what it sounds like: makes a perfect copy of the object and moves it to the room you said to.

In my game, I used this in the following way: I had a DebugRoom, and in it, the object FighterBase. Whenever I started a fight, I'd move the player to a unique Fight room, and then I'd make a clone of FighterBase and move it to the room in question. Using Functions I'd set its alias (The name you see ingame, not the code name), its BaseMaxHealth, its FriendOrFoe, its Description, everything.

This way, I could have just a single FighterBase, and make whatever 1v2 or 4v4 or 4v10 fights I needed, with whatever enemies I needed, whenever and wherever.

This also let me make AoE attacks, with some cleverness using the For Each code:

foreach (ChosenFighter, FilterByAttribute(GetDirectChildren(SpecialFightRoom), "prototype", FighterBase)) {
if (Fighter.FriendOrFoe="Foe"){
SendDamage(ChosenFighter, 50)
}

That looks like a lot! But if you enter it in code-view, and switch back to normal-view, it's not SO scary.

I could even make Buffs by making and cloning a BuffBase object, and moving it INTO individual FighterBase clones, and then checking for every 'clone' of BuffBase (That's what the prototype word is for, it checks WHAT object it's the clone of) and, say, if it's the buff "Health Boost" I increase MaxHealth by 50, if it's "Burning" then my EndOfTurn Function causes 10 damage.

One last thing before I go.

Attributes in attributes in attributes in attributes...

Let's say you go REALLY in depth. You have the player vs 30 orcs in a last stand. You go through the effort of making the player able to target a specific orc with their Frostbolt spell, by creating the attribute Player.Target.

Watch THIS shit:

Player.Target.Health = Player.Target.Health - (Player.Damage/Player.Target.ColdResistance)

You can put attributes in attributes, something called 'nesting' in code. You can do some CRAZY shit by cleverly nesting stuff.

There's a bunch more I can do, but that runs into the territory of giving you the car, not the tools to make one. I hope this helps!

... man this got a lot longer than I'd expected.


Do I have to mess with the code view? Just asking tho
:v
and by the way, thanks. I think I understand ur explanation better - 3 -


Io
Do I have to mess with the code view?

Sort of yes, sort of no? Like, all the code I put up there was in code view because there's really no way to type the non-code view stuff on the forums. You also don't have to code-view the ENTIRE GAME every single time; you can code-view individual fragments with the code-view button on them, and toggle back out of it if you want.

If memory serves you should be able to get by entirely without code view if you don't mind not being able to copy-paste my stuff. The one exception is something I forgot to mention:

If you decide to use my 'Clone a FighterBase' shtick, and it comes time to remove a clone that's outlives its usefulness DO NOT EVER EVER EVER USE THE REMOVE OBJECT CODE!

Remove Object doesn't actually 'remove' it. It just sort of banishes it into hammerspace, but it's still in the game's code, floating around and using up resources.

What you want instead is the Destroy code. Destroy doesn't have a block in non-code view, so if you use it you have to switch to code view, type:

destroy(ObjectYouWantDead.name)

And I do mean .name, not .alias, since destroy wants the object's code name. Once you enter that you can go back to non-code view and there'll be a block for it, but destroy() isn't something you can pick from the list like Print.


Good explanation lo


lmao yes


here's an example combat code for you to study/look-at:

https://textadventures.co.uk/forum/quest/topic/5703/turn-based-combat#39315

ask if you need help on anything or don't understand or need explanation of anything


Advanced or simple combat?
Simple combat:
Stats.

Monster.hp = 100
Monster.attack = 20
player.hp = 100
player.attack = 40

Functions.

player.hp = player.hp - this.attack
this.hp = this.hp - player.attack

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums