Access ACEs of the passed object type from runtime.js?

0 favourites
  • 11 posts
From the Asset Store
This is a single chapter from the "Construct Starter Kit Collection". It is the Student Workbook for its Workshop.
  • Hello, I've just started to "roll my own" plugin <img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" />

    However, I am confused about how to access ACEs (conditions, actions, expressions) inside the runtime.js. For example, I have this piece of code in my edittime.js:

    AddNumberParam("Size", "Enter a map size.");
    AddObjectParam("Object", "An array to store the map in.");
    AddAction(1, af_none, "Generate map", "Generator", "Generate map of size {0} and store it in {1}", "Generate a 2D map", "GenerateMap");
    [/code:1wll1i8q]
    
    I send an Array object form inside the C2,
    
    [img="http://i.imgur.com/J2xQS3e.png"]
    
    Now, from inside my runtime.js, I would like to be able to call, for example, SetX() function of the Array object. I've managed to do something similar with
    
    [code:1wll1i8q]
        	Acts.prototype.GenerateMap = function (size, array)
    	{
                var arrayInstance =  array.getFirstPicked();             
                arrayInstance.set(0, 0, 0, 23);
    	};
    [/code:1wll1i8q]
    
    However, this one will not work
    
    [code:1wll1i8q]
        	Acts.prototype.GenerateMap = function (size, array)
    	{
                var arrayInstance =  array.getFirstPicked();             
                arrayInstance.SetX(0, 23);
                // this one neither: arrayInstance.acts.SetX(0, 23);
    	};
    [/code:1wll1i8q]
    
    I have understood that I can access all the functions which are attached on the [b]instanceProto[/b] object. This makes sense, since I am accessing functions of the instance of the plugin. For example,
    
    [code:1wll1i8q]
    	instanceProto.set = function (x, y, z, val)
    	{
    		x = Math.floor(x);
    		y = Math.floor(y);
    		z = Math.floor(z);
    		
    		if (isNaN(x) || x < 0 || x > this.cx - 1)
    			return;
    			
    		if (isNaN(y) || y < 0 || y > this.cy - 1)
    			return;
    			
    		if (isNaN(z) || z < 0 || z > this.cz - 1)
    			return;
    			
    		this.arr[x][y][z] = val;
    	};
    [/code:1wll1i8q]
    
    However, I see that ACEs are neither attached to the [b]pluginProto.Type.prototype[/b] nor to the [b]pluginProto.Instance.prototype[/b], but directly to the [b]pluginProto[/b]. (The latter is the "shortcut" to the [b]cr.plugins_.MyPlugin.prototype[/b]). So, if I access types and instances functions/properties via type. and inst., how do I access ACEs which are attached directly to the prototype of the plugin?
    
    I want to do all this, in order to learn how to implement plugins/behaviors and to implement a C2 http://ondras.github.io/rot.js/hp/  interface. This will facilitate the job of making roguelikes in C2.
  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • ACE's are function definitions tied to an object type. Instances of that object type may call those functions but must pass the "this" instance reference to the ACE function when calling it.

    As en example many of the plugins i create for my self call the function plugin directly from plugin. To do that when I instantiate an instance of my plugin I perform a look up to find the global function plugin instance and store it.

    Example: I search for runtime instances objects of Function type objects and store the instance reference to a local variable "this.Function.self "

    var objects = this.runtime.objectsByUid;
    for (var i in objects) {
    	if (objects[i] instanceof cr.plugins_.Function.prototype.Instance) {
    		this.Function.self = objects[i];
    	}
    }
    [/code:21b5l0ir]
    
    Then later on somewhere in my code when ever I want to call a function on the event sheet by its name I have to Call the ACE the Action of the function instance i stored.
    
    [code:21b5l0ir]
    this.CallFunction = function(fnName, params) {
    	cr.plugins_.Function.prototype.acts.CallFunction.call(this.Function.self, fnName, params)
    }
    [/code:21b5l0ir]
    
    so now any where in my plugin that I desire I can call a local function "this.CallFunction()" and pass it the name and paramters and it will call that function on the event sheet.
    
    What you need to do is find the instance of the object you want to pass to the ACE function and call the function and pass that instance to it. The best way to learn about this would be to open up some of the other official plugins and review the code and how they work. You can see that many them of call there ACE's in the same manner. The hard part is figuring out how to get the correct instance object to pass to it.
  • Thanks for your thorough and informative answer. I don't know why such a useful functionality should be bogged down by this intricate function call chain / object reference chain.

    Could you please point me to some plugins where I can see the examples of this going on?

    P.S. Here are the first results of making a plugin out of rot.js library:

  • Hey, I've got it ))

    This works and makes sense (although it's a bit convoluted for my taste...):

    var dictInst = dict.getFirstPicked();
    dictInst.type.plugin.acts.AddKey.call(dictInst, "ace", 51);
    console.log("SUCCESS: " + dictInst.dictionary["ace"]);
    [/code:1e4ffs47]
    
    Hope to finish soon rot.js C2 integration and offer an intuitive way to make a roguelike for all those roguelike fans
  • You could access action, condition, and expression.

    http://c2plugins.blogspot.tw/2014/02/reuse-ace.html

  • glad you figured it out. ... I'm not a fan of protoType usage (i extend my class objects using a different method) but to wrap your head around it, its just and extension of the object.

    At the top of each plugin you will something like this

    var pluginProto = cr.plugins_.MyPlugin.prototype;

    "pluginProto" is now a refrence to the MyPlugin plugin prototype extension (not any instance of it but the object definition it self)

    further down in a plugin you will see something like this

    function Acts() {};

    Acts.prototype.DoSomething = function(param1){

    //Code in here that does stuff to the instance that called it.

    }

    This is building a set of actions to add to this object.

    Lastly those actions are added to the object by something like this

    pluginProto.acts = new Acts();

    "pluginProto.acts" is the same as typing "cr.plugins_.MyPlugin.protype.acts"

    So the final location of the DoSomething() function is "cr.plugins_.MyPlugin.protype.acts.DoSomething"

    Now in Javascript if you were to just call the function "cr.plugins_.MyPlugin.protype.acts.DoSomething(param1)" the function would have no refence to the instance it is supposed to do work on.

    To pass the instance you need to add a .call so it would be "cr.plugins_.MyPlugin.protype.acts.DoSomething.call(instanceObject,param1)"

    And thats plugin ACE function calling in a nut shell

  • Hey, troublesum, thanks for the great explanation!

    I already quite figured it out on my own (thanks to your help from the previous post), but I appriciate always a clear and systematic explanation. Stays here for the benefit of the C2 mankind Plus, I think it should be in the official manual. It would have saved my time, anyway...

    The only critique goes to the sequence of your emails... The last one should have been the firt one

  • I would *strongly* recommend you do not write plugins that directly access other plugins. It breaks encapsulation and is brittle. For example we may go ahead in future and change how the Array object works to fix some bug or change some feature, and this will break everything that depends on it like this.

    Also, it's less useful for users. You force them in to a specific workflow. For example if you at some point run an action in another object, then the user is locked in to that dependency and can never alter it. If on the other hand you run a trigger, then the user can place an action in that event to do that task, or they can do something else, perhaps using a different third party plugin or some alternative feature. It's also easier to understand since you can see what's happening, instead of there being under-the-hood invisible magic causing actions to run unexpectedly. Consider that in the entire C2 engine, actions never run except where they have been added visibly in the event sheet, and a plugin that uniquely breaks that rule will be uniquely surprising. Users can also more easily test by adding logging to triggers, temporarily disabling the action, etc.

    Yes it's possible, but you will design inflexible, breakable plugins - please think of other ways to design your plugin.

  • Thank you for your response. I should have supposed that there is a good reason behind the absence of a straightforward way to access other plugins' ACEs. I think that everyone, including me in the first place, would appreciate very much a manual page or a blog post on plugin development best practices.

    While we are at it, I just wanted to share with you a few bumps i ran into while I was reading the SDK manual. For example, the Runtime reference explains how to access the runtime. However, I had to figure out on my own how to access layouts, layers, types and instances. Maybe a small adition to the first paragraph of the corresponding pages would facilitate the access.

    Be that as it may, I am thankful for this wonderful piece of software. Less frustration, more fun, elegant solutions

  • Ashley I understand. That's why I have not released any of my plugins that directly access other plugins to the general public. I don't want to have to maintain them so i get where you're coming from.

    PS. But my plugin (unreleased) that ties the Multiplayer and Function plugin together to allow for calling functions on all peers at the same time with a single call is pretty sweet though ... Taking two powerful plugins and creating a wrapper to combine their functionality adds an amazing amount of power to my projects. I wouldn't be so harsh on others (or myself) that want to do this so long as we respect the C2 eco system. I can actually have a game engine now that is synced across all peers controlled by the host because the host has functional control over everything with super simple control.

  • Ashley

    It is a trade off.

    The dependence is a risk, I agree. But it is also a chance to reuse other code to reduce the maintain cost.

    Btw, ACE of official plugin is very stable, my plugins had not broken caused by the ACE depence of official plugin in the past 3 years.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)