On modifying pre-existing code (Inheritance?)

Hi again.

I’m trying to stick as much repetitive code as possible into custom classes, but I hit a snag as to how to, or whether it is possible, to make small modifications to relatively long objects. I know how to use Inherited() to add something to the end of a pre-existing method, but not how to mess with chunks from the middle.

For instance, here is Slime’s behaviour, represented by the agenda item slimeAttackAgenda:

+slimeAttackAgenda: AgendaItem isReady = (inherited() && player.location == slime.location) initiallyActive = true invokeItem() { local roll = rand(100); if (roll >= 50) "The Slime stares blankly and loses its turn. "; else { local roll = rand(100); local hitChance = 100 - player.SPD; if (hitChance >= roll) { "The Slime charges at you! "; player.LoseHP(slime.ATK); } else "The Slime charges at you, but its attack missed! "; } } ;

Suppose I want a lot of this to work much the same for other monsters, more or less like this:

class MonsterAttackAgenda: AgendaItem isReady = (inherited() && player.location == slime.location) initiallyActive = true invokeItem() { local roll = rand(100); local hitChance = 100 - player.SPD; if (hitChance >= roll) { "Monster attacks you message. "; player.LoseHP(slime.ATK); } else "Monster missed message. "; } ;

This would be generic monster behaviour. From here, I would want to customize the two double quoted strings for each monster, as well as the “slime” in

player.LoseHP(slime.ATK);

since I would need to change that to point to each respective monster, else all of them would be using slime’s ATK property to calculate damage.

Additionally Slime has another random 50/50 chance of just staring blankly and doing nothing instead of following with all the hitChance and attack behaviour. That’s there just as a placeholder for some other customized behaviour I might want to implement.

Basically, the point of this exercise is that I want to keep a block of code in a class definition and freely mess with chunks of the content on individual instances. Is this doable?

You have the right idea. The trick is to keep the core logic the same for all members of the class, and limit the differences to properties that can be easily modified.

Mostly this means factoring out any strings, and being careful with the way you reference properties.

class MonsterAttackAgenda: AgendaItem
	isReady = (inherited() && gPlayerChar.location == owner.location)
	initiallyActive = true
	invokeItem()
	{
		local roll = rand(100);
		local hitChance = 100 - gPlayerChar.SPD;
		if (hitChance >= roll)
		{
			hitMsg();
			gPlayerChar.LoseHP(owner.ATK);
		}
		else
			missMsg();
	}

	hitMsg  { "The <<owner.name>> charges at you! "; }
	missMsg { "The <<owner.name>> charges at you, but its attack missed! "; }
	owner = location
;

yellowSlime: Monster 'yellow slime' 'YELLOW SLIME' @Redroom
	ATK = 100
	SPD = 100
;

+ MonsterAttackAgenda
	invokeItem()
	{
		local roll = rand(100);
		if (roll < dazeChance)
			dazeMsg();
		else
			inherited();
	}

	dazeChance = 50
	dazeMsg { "The <<owner.name>> stares blankly and loses its turn. "; }
;

purpleSlime: Monster 'purple slime' 'PURPLE SLIME' @Redroom
	ATK = 1000
	SPD = 100
;

+ MonsterAttackAgenda	
	hitMsg  { "The <<owner.name>> slimes you! "; }
	missMsg { "The <<owner.name>> quivers with rage! "; }
;

That worked. I ended up fragmenting the more of the processes into methods so that I could override them individually if necessary or just have inherited() let it all carry as default.

I have a question that has absolutely nothing to do with this but doesn’t really warrant a new thread: how do I override a preCond in an item? thing.t tells me this can be overriden on an individual basis but doesn’t bother to tell me how, and simply leaving it off from the custom dobjFor(Drink) doesn’t seem to do it. For instance, I made a fountain and set everything up to be able to drink from it, but I can’t seem to get rid of the preCond = [objHeld] check, which of course always fails since the object is a Fixture.

+fountain: Fixture 'water/fountain/pool' 'Water fountain' "A fountain. " dobjFor(Drink) { verify() {} action() { "You took a sip" ; } } ;

You override the list of PreCondition objects with an empty list.

preCond = []

That should do the trick.