Using Pseudo Classes
NOTE: THIS PROBABLY ISN'T ROLLBACK SAFE
Walkthrough
Haxescript does not officially support the definition of classes, however, this doesn't mean you can't implement them yourself, which is what you'll be learning how to do here.
Here's a documented example on how to make a Pseudo Class
Minimal Example
haxe
function playerHitCounter(player: Character) {
// Variables to keep track of state
var foeCounts = [0,0,0,0]
// getter function to get values
getFoeHitCount(foe:Character): Int {
var foePort = foe.getPlayerConfig().port;
return foeCounts[foePort];
}
incrementFoeHitCount(foe:Character): Int {
var foePort = foe.getPlayerConfig().port;
Engine.log("Player "+ (foePort+1) + "got hit " + foeCounts[foePort] + " times!");
foeCounts[foePort] = foeCounts[foePort] + 1;
}
// Event Listener Function
function onHit(e:GameObjectEvent) {
var foe:GameObject = e.data.foe;
if (foe.getType == EntityType.CHARACTER) {
incrementFoeHitCount(foe);
}
}
// Event Listener Helper
function startEvents() {
player.addEventListener(GameObjectEvent.HIT_DEALT, onHit, {persistent:true});
}
function stopEvents() {
player.removeEventListener(GameObjectEvent.HIT_DEALT, onHit);
}
return {
start: startEvents,
stop: stopEvents
};
}
hitCounter = playerHitCount(self)
hitCounter.start(); // Starts the Counter
hitCounter.stop(); // Stops the Counter
Complex Example
haxe
function createTrippingClass(player: Character) {
// Instance variables can be defined using var
var total_trips = self.makeInt(0);
var active = self.makeBool(true);
var timerId = self.makeInt(-1);
// we can also access variables or perform actions using functions here
// Gets the number of times we tripped over the player
function get_trips():Int {
return total_trips.get();
}
// Returns true if the event listeners and timers are active
function isActive():Bool {
return active.get();
}
// Manually increments the trip counter
function add_trip():Void {
total_trips.inc();
}
// Reset the trip counter
function reset_trips():Void {
total_trips.set(0);
}
// Trip the player, also updates the counter
function trip():Void {
player.toState(CState.CRASH_BOUNCE);
add_trip();
}
// We can create timers and event listeners!
// First we create a function we're gonna use for the timer,
// creating it separately makes it easier to pause and resume it
function onInterval() {
if (player.isOnFloor()) && (player.inStateGroup(CStateGroup.DASH)
|| player.inStateGroup(CStateGroup.RUN)
|| player.inStateGroup(CStateGroup.WALK))
{
if (Random.getInt(0, 15) == 5) {
trip();
}
}
}
// We also define the function for the event listener separately here, for the same reason as above
function onStateChange(e:EntityEvent) {
var toState = e.data.toState;
var grounded = player.isOnFloor();
if (grounded && toState == CState.DASH) {
if (Random.getInt(0, 6) == 3) {;
trip();
}
}
}
// Now we create the timer here, the timer returns an id we can use to remove it later
timerId.set(player.addTimer(60, -1, onInterval, {persistent: true}));
// Here we create the event listener
player.addEventListener(EntityEvent.STATE_CHANGE, onStateChange);
// A helper function for outsiders to be able to manually enable tripping
function resumeEvents() {
if (!active.get() && timerId.get() < 0>) {
player.addEventListener(EntityEvent.STATE_CHANGE, onStateChange);
timerId.get(player.addTimer(60,-1,onInterval), {persistent:true});
active.set(true);
}
}
// A helper function for outsiders to be able to manually pause tripping
function pauseEvents() {
player.removeTimer(timerId);
player.removeEventListener(EntityEvent.STATE_CHANGE, onStateChange);
active.set(false);
timerId.set(-1);
}
// Now we return an object with all the functions
return {
add: add_trip,
reset: reset_trips,
get_count: get_trips,
pause: pauseEvents,
isActive: isActive,
resume: resumeEvents,
trip: trip
}
}
Actually using this "Class"
For convenience we can create a our own constructor, think of how you use Sprite.create
, Container.create
or Point.create
so as a top level variable we have and we can just embed the function inside, keep in mind that you need to define the function BEFORE YOU DEFINE THIS AND NOT AFTER.
haxe
var TrippingMachine = {
create: createTrippingClass
};
var HitCounter = {
create: playerHitCounter
};
"Attaching" the class to players
From the perspective of the player being self
.
For the simple example:
haxe
var hitCounter = TrippingMachine.create(self);
tripper.start(); // we can call its functions from the outside!
tripper.stop();
haxe
var tripper = TrippingMachine.create(self);
tripper.trip(); // we can call its functions from the outside!
tripper.pause();