For Total Conversions and projects that don't otherwise fall under the other categories.
Forum rules
The Projects forums are only for projects. If you are asking questions about a project, either find that project's thread, or start a thread in the General section instead.
Welcome to the Project: Blackfire announcement thread where you can get your daily dose of teasers and status updates on the project that will change the way you will mod doom.
So I'm sure a lot of you have been wondering what the hell this project is and what the deal is with the forum group here on the ZDF. Basically Blackfire is a two part project: One part being the SDK, and the other being a total gameplay mod that is a lot of fun and can act as a working example of sorts for people to learn from.
The goals of Project: Blackfire are simple:
To provide a means of automation that enables the community to have the ease of use, and flexibility, that they need in order to accomplish more scripting heavy effects and features.
To make ACS easier to use on more complex concepts
To provide a set of actively collected data that will open the doors to greater flexibility in the language.
One of the big things that Blackfire is meant to promote is flexibility and the ability to provide this flexibility in ways of which that would enable an individual to pass new forms of data over new mediums without the necessity of any overhaul to any part of the compiler for ACC or to ZDoom itself. What this means is that the Blackfire SDK is nothing more than a collection of ACS libraries, written in a manner of which to be extremely adaptable to any project you have. This is done all while not having to do any heavy amount of scripting.
You do not even need to compile these libraries into your map, they will run regardless of the fact it is in LOADACS or in the map's behavior file. Some modules for the SDK may require you to load some forms of data into a map inside an open script, however.
Current feature set for the library includes:
Memory allocation routines to enable OOP design and sharing of multiple forms of data across scripts. This basically means that scripts now have the ability to pass pointers as well as standard variables. (Pass an array as a function/script parameter anyone?)
Plugin manager that enables the direct control of the distribution and execution of code across multiple instances of the game.
Global player stats class that enables saved player stats across maps and can be read to save and dump data to a log file in a format of which that can be fed back into the game without modification.
Globalized universal XP plugin that is formula based so you can set your level cap to whatever you want and have it still work in MP. Uses the Plugin Manager to operate.
A new menu architecture that allows for full interaction in a variety of environments, off-line and online. Also comes with a WYSIWYG editor that allows you to build your own menus with custom collision data, and generates all the code to use the menu. Requires only minimal modifications to use the code to apply to what you need.
A new dialog and shop system architecture that allows for simple design of dialog trees and creation of simple shops. Also allows for custom window definitions made with the Menu Utility that can replace the default and can be set on a per-dialog/shop basis. Also allows for the modular creation of dialog and shop listings that can be attached to any thing that can set its activator to the player that interacted with it through a simple script call with 1 argument.
A status manager for the plugins that enables real-time control of available code running through the engine. This is also where you would allow for the control of server features and plugins while in-game. There isnt a GUI for this yet, as I made this before the menu system, but there will be one for it soon.... When I have enough button graphics
Remember to stay tuned to this thread for your latest updates and event announcements relating to the project!
As always, I appreciate any and all input that can be given for this. Let me know if you have any questions or ideas you'd like to see!
It's kinda hard for me to provide screenshots of stuff like this in action, but I figure I can just keep posting teasers here until this gets done. For now, instead of screen shots, I shall give you all some sample code to ponder from the new shop menu architecture. This is example code showing a basic fundamental usage of the new architecture to define and create your own shop menu.
UPDATE 2/29/12 - Here is the first demo video showing a basic walkthrough of using the Menu builder utility:
EDIT: Oh yeah, turns out WildWeasel shall be one of the first to be using this framework in his mod "WWHC Cold Hard Cash" for ZDoom. I believe he is just using the dialog/shop system, but still awesome none the less
#include "zcommon.acs"
#include "defines.acs" //blackfire defines file
#import "blackfire.acs" //core blackfire plugin library
#import "dialog.acs" //library for loading and working with your shops and dialogs
//**----------------------------------**
//When you go to make a selling/buying list
int myfirstshoplist[5]; //You always start by defining it as a map array.
//The reason why you make these is to store the
//information necessary to load that object into
//a list.
//These arrays are meant to do nothing more than store your defined shop items.
//after defining these arrays, you're going to want to create a variable to store the
//location in memory of your buying/selling lists that are meant to be used in-game.
int Armorerbuylist;
int armorersellist;
//and that's all you need to do to define your initial variables to be used as
//shop inventory objects. Look below for usage on the functions that load the data into your arrays
//**----------------------------------**
//A NOTE ABOUT DEFINING SOUNDS:
//Normally, inside this plugin, a sound is played by spawning an object
//on top of the player. This gives the engine the ability to keep sound effects
//from overlapping. Also if you are trying to use a global dialog, you can give
//the object Line-of-sight checking so different dialog noises can be played
//depending on where the players are in the map.
//When you use the flag PLAYSOUNDLOCALLY, you override this feature. The sound effect
//is played through localambientsound() instead of spawning the string given in
//the sound parameter for DefineDialog();
Script 1 OPEN //This is where you'd put all your object definitions.
{
//we're going to start by making a small intro dialog before showing the shop menu
DefineDialog(100, //The ID to give this dialog
"DSPAIN", //Sounds effect to be used
"Apothem:", //This is the title of the dialog box.
"Hello! And welcome to my little shop of horrors! You can get all \n
you need here. And feel free to try out any of the guns! \n
My motto is: if you cant try it, why should you buy it?!", //Body of the dialog in the window
PLAYSOUNDLOCALLY, //Flags to be set.
350, //Hold time (in tics)
101); //The next dialogID to go to. If this is 0, it clears all dialog related elements
//off the screen of the currently loaded dialogID.
DefineDialog(101,
"vendingmachinesoundgoeshere", //You'd put the sound that you want played when the shop menu opens here
"The ApotheShop", //Title of the shopping menu goes here
"Your one stop shop for all your military needs!", //Description/friendly message of the shop goes here
PLAYSOUNDLOCALLY,
0, //Since we're not doing anything special with this DID, we can set holdtime to whatever.
0); //We want the window to clear and this to be the last dialog, so we set the next one to 0
//to signal termination.
//DEFAULT GROUPID'S FOR CREATING SHOPOBJECTS
//SHOPGROUP_ARMOR 1
//SHOPGROUP_WEAPONS 2
//SHOPGROUP_POWERUPS 3
//SHOPGROUP_AMMO 4
//SHOPGROUP_MISC 5
//Not required but can help if you make a large enough list and
//want the engine to sort them.
myfirstshoplist[0] = DefineShopObject("GreenArmor", NORESALE, 100, SHOPGROUP_ARMOR);
myfirstshoplist[1] = DefineShopObject("BlueArmor", NORESALE, 200, SHOPGROUP_ARMOR);
myfirstshoplist[2] = DefineShopObject("Field Kit", NORMQUAL, 50, SHOPGROUP_POWERUPS);
myfirstshoplist[3] = DefineShopObject("Super Pistol", HIGHQUAL, 1000, SHOPGROUP_ARMOR);
myfirstshoplist[4] = DefineShopObject("PLAYGOLD", NORESALE|ISCURRENCY, 1, 0);
//when defining currency, you must set the flag ISCURRENCY for it to be recognized correctly.
//You can define something as currency and still allow it to be bought/sold
//The currency's base value is how many units of that currency is represented when you carry 1 piece
//of it in your inventory.
//now that we've defined all the things we're going to buy and sell any shop, lets create the
//list of inventory for a particular list.
//function int defineBuyingList(int currencypointer, int flags)
//int Currencypointer - the location in memory where the object data for your currency to be used on
//this list is stored. The location data is returned whenever you call a Define* type of command. All
//this means in the current example is that we would want to use the value of myfirstshoplist[4] here.
//int flags - Read the documentation on which flags are which somewhere else :P
//(basically that means I haven't really decided on any of that yet.)
//The flags will have to do with modifying the rates of which the shopkeeper buys and sells to the player
//on top of the base settings on the object. You will also be able to override certain flags like
//NORESALE and SHOP_HIDDEN for all objects in this list.
//By default, a shop list can contain up to 128 items.
armorerbuylist = definebuyinglist(myfirstshoplist[4], 0);
armorerselllist = definesellinglist(myfirstshoplist[4], 0);
//From here, all that is left is to attach objects to these lists.
//for this we use the following function:
//function int AddObjtoShop(int objectpointer, int destination)
//int objectpointer - the location in memory of the object that you want to store to the list.
//in this example we will be using indexes 0-3 of myfirstshoplist[]
//int destination - the location in memory of the list you want to use.
//in this example we will be using the values of armorerbuylist and the armorerselllist.
AddObjtoShop(myfirstshoplist[0], armorerbuylist); //compile the buying list
AddObjtoShop(myfirstshoplist[1], armorerbuylist); //for our armorer NPC
AddObjtoShop(myfirstshoplist[2], armorerbuylist);
AddObjtoShop(myfirstshoplist[3], armorerbuylist);
AddObjtoShop(myfirstshoplist[2], armorerselllist); //compile the selling list
AddObjtoShop(myfirstshoplist[3], armorerselllist); //for the NPC
//And you're done making your shop keeper lists!
//At this point, all you have to do is attach your buying and selling lists to any dialog ID's
//that would be used by your NPC to initiate the trade screen.
//You do that by using the following functions:
//function void attachselllist(int dialogID, int buyinglistpointer)
//function void attachbuylist(int dialogID, int buyinglistpointer)
//int dialogID - the dialog id that you want to attach this list to.
//int buyinglistpointer - the location in memory of the list that you want to use on this DialogID.
//For this example, we would be using armorerselllist and armorerbuylist.
attachbuylist(101, armorerbuylist);
attachselllist(101,armorerselllist);
//AND YOU'RE DONE!
//basically at this point, all you need to do to call the dialog up to load the shop menu is
//make an actor whose special calls the DIALOG_LOADER script with it's first parameter
//being the dialog ID you want to start with.
//so for this example it would be:
Acs_executealways(DIALOG_LOADER, 0, 100,0,0);
//As long as the player is the activator of that script, it will work appropriately.
}
Last edited by Apothem on Wed Feb 29, 2012 4:16 pm, edited 6 times in total.
Apothem wrote:
Current feature set for the library includes:
Memory allocation routines to enable OOP design and sharing of multiple forms of data across scripts. This basically means that scripts now have the ability to pass pointers as well as standard variables. (Pass an array as a function/script parameter anyone?)
Plugin manager that enables the direct control of the distribution and execution of code across multiple instances of the game.
Global player stats class that enables saved player stats across maps and can be read to save and dump data to a log file in a format of which that can be fed back into the game without modification.
Globalized universal XP plugin that is formula based so you can set your level cap to whatever you want and have it still work in MP. Uses the Plugin Manager to operate.
A new menu architecture that allows for full interaction in a variety of environments, off-line and online. Also comes with a WYSIWYG editor that allows you to build your own menus with custom collision data, and generates all the code to use the menu. Requires only minimal modifications to use the code to apply to what you need.
A new dialog and shop system architecture that allows for simple design of dialog trees and creation of simple shops. Also allows for custom window definitions made with the Menu Utility that can replace the default and can be set on a per-dialog/shop basis. Also allows for the modular creation of dialog and shop listings that can be attached to any thing that can set its activator to the player that interacted with it through a simple script call with 1 argument.
A status manager for the plugins that enables real-time control of available code running through the engine. This is also where you would allow for the control of server features and plugins while in-game. There isnt a GUI for this yet, as I made this before the menu system, but there will be one for it soon.... When I have enough button graphics
Holy shit. Didn't see this coming. Imagine the capabilities gained.
I hope it turns out to be robust but I have no doubts.
Xaser wrote:I'm still scratching my head over how you've managed to implement half the stuff listed here.
Great stuff though. Hopefully it's as awesome as it's chalked up to be.
Well, one of the things that will help make it awesome is lots of documentation and examples. Sadly there is a lot more to it than just simply 'making a text file'. I need to do documentation for each individual piece. Later documentation will include walk through videos and extra tools to help you get your job done faster.
This is the big thing that is holding me back on some of this getting done faster, is that I basically have to do double work. One time through for writing and coming up with the framework for a module, and then another time through to document and give examples.
Thank god I comment my code and make it legible enough to do all of it without getting lost. Speaking of which, if anyone is willing to sit down with me and help me do the documentation on this it would be greatly appreciated.
TheDarkArchon wrote:Ah, so THIS is what the ACS malloc babble on IRC was for.
Also, I think your title is a bit out of date there.
Indeed
Malloc is a cornerstone to this project and enables the OOP-style that this library has. Pretty crazy how it works. I'll be doing a video on its usage and features sometime soon....
Also what do you mean by my title being out of date? This is the same one I've always had. Or is it because Zdoom cant make my head go boom because I lost it ages ago?
Apothem wrote:
Also what do you mean by my title being out of date? This is the same one I've always had. Or is it because Zdoom cant make my head go boom because I lost it ages ago?
I'm thinking more "ACS can't make your head explode since you've officially made it your bitch"