New inventory system in development

This is the place to go if you need help with creating your Mod/Mutator.

Moderator: Forum Moderators

Post Reply
Vaptor
Programmer
Programmer
Posts: 20
Joined: Mon Jun 12, 2006 4:08 pm
Contact:

New inventory system in development

Post by Vaptor » Thu Oct 02, 2008 3:14 pm

heres some of my own ideas i created new classes to handle stuff they are only prototypes they are untested code and still unfinished if some one feels inspired feel free to borrow some of the code on this post.



//==========================================
// based off CoinS base class by vaptor
// rebuilt to destroy the inventory so we can rely on useing rpgstatsinv as base of the entire artifact inventory
// to do add new functions and replace hud interactions in rpgstatsinv
//
// Purpose of this code
// inventory items become a burden when too many exist
// so its nessary to simulate the ones in inventory with data
//
// Benifits and drawbacks of this method
//
// REmoves inventory items that are held in player inventory allowing more new objects to be created
// requires all inventory interactions to run through rpgstatsinv such as toss artifact
// requires weapons to store items as a string of numbers
//
//[[[[[[[[[[[[[[ main points to understand]]]]]]]]]]]]]]]
//
// the most efficent way to keep the new inventory is to turn all inventory into one Variable intiger...
// ... thus each digit is a placeholder for a diffrent item (example below) = translation
// 000001000300050002500 = 1x force5, 3x healer, 5 sturdy, 2 poison, 5x poison5
//
//>> inorder to store the inventory artifacts will be Translated from a number value and shown on the hud
//
//
// requres at most 3 or 4 item conversions to translate the
//===============================================================
class ArtifactWopCoin extends RPGArtifact;

var MutUT2004RPG RPGMut;
// itemid is just a fast refrence to the item array so we avoid excess array conversions when we pickup alot of items
var() int ItemId;

state Activated
{
function BeginState()
{
local Pawn P;
local RPGStatsInv StatsInv;

RPGMut = class'MutUT2004RPG'.static.GetRPGMutator(Level.Game);
P = Instigator;
StatsInv = RPGStatsInv(P.FindInventoryType(class'RPGStatsInv'));
if (StatsInv != None )
{
StatsInv.addinv(ItemID);
}

p.nextitem();
Destroy();
GotoState('');

}
}

//this is only a example and does not have a pickup or icon

defaultproperties
{
bCanHaveMultipleCopies=true
//PickupClass=Class'FULL_Guard.ArtifactGOLDPickup'
//IconMaterial=Texture'FULL_Guard.Icons.InvulnerabilityIcon'
ItemName="temp"
itemid=0
}

//===========================
// by Vaptor item simulator control
//
// this is only a outline for useing data only approach for WeaponModifiers
//
// my main goal here is to create a core function to handle the various weapon effects with out dealing with the individual objects
//
//reason for idea is simple by using raw data rather than haveing a inventory item we can free up space needed for new monsters or actors in the global object pool
//
//also suspect another problem we have in later waves some times can be atributed to multiple spawn actor failures for emitters ect due to inventory objects filling the remaining object pool space
//spawn actor failures might also affect item refrence transfers for instance rpg weapons will lose their modifed weapon ( weapon that is spawned and used as a template)
//
//===========================

class wopCoreControl extends actor Abstract;

var class< WeaponModifier > EffectClasses[54]; // im not really sure how many modifers we have now this could take a while


////////////////////////////////////////////////////////////////////////////////
//current weapon changes will include holding the powerups as a definded interger array with members matching the class array defined in this class
// mostly purpose of this class is to act as a handler for communication between a weapon of power and weapon modifiers
/
// makes up for not actually keeping the object this way we can fake the items in the inventory list and reduce chances players will get the get crashes from powerup count after we revise it
//rpgstat revision i have in mind will show the weapon modifers that have a value of 1 or higher on the list of useable items
//
////////////////////////////////////////////////////////////////////////////////

//=====================================================================
// first function does most everything like appling poision damage or knock back and even healing effects to
//=====================================================================
Static function GetEffectforitem(weaponofpower CurrentWeapon, int itemnumber,int powerlevel, Optional Pawn Victim) // useing optional will not throw errors if the effect does not do damage dies before this runs for any reason
{
if(currentweapon != none)
{
if(itemnumber > -1) // it should never be -1 if it is something is not working correctly
{
//process effects is a function that has a vital role we use converttoclass to get the file that does the effect of the powerup in question this is executed instead to replace sorting though the inventory over and over for the same effects , so this works faster with less cpu
if(victim == none)
{
currentWeapon.ProcessEffects(convertToclass(itemnumber),powerlevel); // this effect has no victim
}
else
{ // note: currentweapon is the Weapon of power in use that has acess to the rpg alterations and the holder of the weapon

CurrentWeapon.ProcessEffects(convertToclass(itemnumber),powerlevel,Victim); // both functions execute the effect code directly in the weaponofpower itself makes it easyer to acess ingame stuff from there. point of execution might need to be changed from the weapon only if it dosen't work out for some unexpected reason.
}
}
}

}


//===========================================================================
// just a conversion table that pulls the class it self from the defined list in this class based on its id number
// mostly this is for makeing it more efficent by useing a number for anything that doesn't require its full class name
//
// the wepon of power will have a similar array but it will contain numbers for how many of what it has applied instead of class names
// this second function is expected to get a lot of use so its designed to be simple and no extra features
//===========================================================================
Static Function Class<WopEffect> ConvertToClass(int ItemID)
{
//todo return the correct class for the powerup effect functions change the number in the database to the class containing effect code
if(ItemID > -1)
{
Return (Default.Conversionlist[ItemID] ); // keep the list of powerup classes in this file due to restrictions that cause static functions to be prohibited from reading data that is not present at compile time and limited to defaults when its not replicated
}
else
{
return 0; //if a error happened we get this
}
}

//=======================================================================================
// the third function is just to do adding powerups and checking should be done in the weapon of power but new functions need added there
//
// class'weaponofpower' is the child of class'rpgweapon' just to remind you which class Needs new code
//
// function ChangeModifier(int Powerup_ID,int mode)
// {
// Switch(mode) // mode 0 is add item to effect list
//
// }
//=======================================================================================
static function bool addtoweapon( Rpgstatsinv ActiveRpgdata, weaponofpower currentWeapon, int itemfromList)
{
if(ActiveRpgdata != none) // found the datastorage actor that rpg uses to keep the ingame active player data , also used for send recieve of commands that require client involvement at some point
{
if(ActiveRpgdata.haswopitem(Itemfromlist)) // use rpgstatsinv on the local player to check if he actually has any of that item stored as data only
{

if(currentweapon != none) //safeguard against lag
{
if(currentWeapon.HasSpaceforitem(Itemfromlist) ) // check if weapon has empty slots and if the powerup is allowed include checks for similar powerups that prevent use of others. for superspeed powerup we can't allow another speed powerup
{
currentWeapon.changemodifier(ItemFromList,0); // tell the weaponofpower class that holds powerup data to add this item to its active effects list that we need to add

Return True; // check to make sure useing return dosen't disrupt adding items its unlikey but i got a wierd feeling about it.
}
else
{
Return False; // nope can't add the item by returning false we can use this function to trigger a message also if we want to saying can't add to weapon
}
}
}

Return False;
}
////////////////////////////////////////////////////////////////////////////////
// some examples class'poisionmodifier' is by no means a valid name it probly needs packages too in the name
//=========================
defaultproperties
{
Effectclasses[0]=class'PoisionModifier'
^ all the other modifiers inbetween \/
Effectclasses[54]=class'PoisionModifier'
Configuration= //still needs one

}
another related prototype

//==============================================
//next gen spells that will not burden the server vap
// in development
//=============================================
class Artifactspellbook extends RPGArtifact
config();

var float nextcasttime; // restraint on spell cast time to recover
//=================================== for holding refrences
var bool bnewspell; // make the client handle updateing the array
var Bool Bcasting;
var int curspell; // selected spell client convert from index
var int clientspellarray[30]; client spell array avoid replication! if possible keep this client only
var int mana;

Var class< spell > SpellList[30]; // for spells


replication() // may need revisions
{
reliable if(Role < Role_Authority)
spellnext,spellprev,CAST; // client curent spell

reliable if(role < Role_Authority || Role == Role_authority)
mana,curspell;
reliable if(role == Role_Authority)
rebuildlist,bnewspell,manaadd,manadrain; // server control is on allowed spells
}

//======================== spell selection ===============================
exec function Spellnext() // keybind for next spell
{ // to do: make current spell = to a class array number
local int prevnum;
local class< spell > magics;
prevnum=curspell;

magics=getspell(curspell,1);

if(prevnum == curspell)
{
warn(" no change in curspell variable");
}
//todo figure out more logic
}

exec function Spellprev() // key bind for previous spell
{
local int prevnum;
local class< spell > magics; // not used here all we do is cycle

prevnum=curspell;

magics=getspell(curspell,-1);

if(prevnum == curspell)
{
warn(" no change in curspell variable");
}
//todo figure out more logic
}

//===========================================================================
// needs alot of work yet
//=============================================================================
static function class< spell > getspell(int spellnumber,int direct)
{
local int spi;

spi=spellnumber;
currentspell=spellnumber;

if( currentspell+direct > 30)
{
currentspell=-1; // go to the first spell
}

if(currentspell+direct < 0) )
{
currentspell=31; // go to last by jumping to 30
}

currentspell=currentspell+direct;

dowhile(clientspellarray(currentspell) == 0) // if its 0 the player doesn't have that spell yet so keep looking
{
if( currentspell+direct > 30) // prevent the number from exceeding array size
{
currentspell=-1; // go to the first spell
}

if(currentspell+direct < 0) )
{
currentspell=31; // go to last by jumping to 30
}

currentspell=currentspell+direct;

if(currentspell == spi)
{
break; // we are back where we started cancel this loop
}
}

curspell=currentspell;

return(default.SpellList[currentspell]); // something like this
}

EXEC Function CAST() // needs key binding
{
local class< spell > thisspell;

if(Nextcasttime < level.timeseconds)
{
thisspell=static.GetSpell(curspell,0);
// tempoary replace the method for geting spell later
if(thisspell != none)
{
nextcasttime=level.timeseconds + thisspell.default.casttime;
thisspell.Static.Cast(instigator,self); // for doing stuff
}
else
{
warn(thisspell);
}

}
}

function manaDrain(int Drained)
{
if(0 < mana-drained)
{
mana-=drained;
}
else
{
mana=0; // prevent going negative
}
}

function manaadd(int added)
{
if(default.mana+1 > mana+added)
{
mana+=added;
}
else
{
mana=default.mana; // prevent exceeding max
}
}
//==================================================================================
Function RebuildList(int spelltoenable) // not finished with this logic yet purpose to pass in new spells
{
bnewspell=true;
curspell=spelltoenable; // ok now my head hurts ill try to finish this logic later after i organize my thoughts.
}

defaultproperties
{
clientspellarray(0)=1 // 0 = can't use this spell 1= can use only used durring geting next spell
clientspellarray(1)=0
clientspellarray(2)=0
clientspellarray(3)=0
clientspellarray(4)=0
clientspellarray(5)=0
clientspellarray(6)=0
clientspellarray(7)=0
clientspellarray(8)=0
clientspellarray(9)=0
clientspellarray(10)=0
clientspellarray(11)=0
clientspellarray(12)=0
clientspellarray(13)=0
clientspellarray(14)=0
clientspellarray(15)=0
clientspellarray(16)=0
clientspellarray(17)=0
clientspellarray(18)=0
clientspellarray(19)=0
clientspellarray(20)=0
clientspellarray(21)=0
clientspellarray(22)=0
clientspellarray(23)=0
clientspellarray(24)=0
clientspellarray(25)=0
clientspellarray(26)=0
clientspellarray(27)=0
clientspellarray(28)=0
clientspellarray(29)=0
clientspellarray(30)=0
//for now the spells listed below don't have server config replication so i put them here "spelllist"
spelllist(0)=class''
spelllist(1)=class''
spelllist(2)=class''
spelllist(3)=class''
spelllist(4)=class''
spelllist(5)=class''
spelllist(6)=class''
spelllist(7)=class''
spelllist(8)=class''
spelllist(9)=class''
spelllist(10)=class''
spelllist(11)=class''
spelllist(12)=class''
spelllist(13)=class''
spelllist(14)=class''
spelllist(15)=class''
spelllist(16)=class''
spelllist(17)=class''
spelllist(18)=class''
spelllist(19)=class''
spelllist(20)=class''
spelllist(21)=class''
spelllist(22)=class''
spelllist(23)=class''
spelllist(24)=class''
spelllist(25)=class''
spelllist(26)=class''
spelllist(27)=class''
spelllist(28)=class''
spelllist(29)=class''
spelllist(30)=class''
mana=100;
CostPerSec=0
PickupClass=Class''
IconMaterial=Texture''
ItemName="Spellbook"
}

User avatar
BaronVonRotterdam
UT2004 Server Admin
UT2004 Server Admin
Posts: 2603
Joined: Thu Feb 16, 2006 9:42 pm
Location: The Terrible State (New York)
Contact:

Post by BaronVonRotterdam » Sun Oct 05, 2008 9:04 pm

Vaptor, you are on the way to ruling the world dude. Top notch work as always :)
| ASRock Fatal1ty X470 | AMD Ryzen 3700x @Stock | 32GB DDR4 3200 mHz | Zotac GeForce RTX 2060 Super | Dell S2417DG |

Vaptor
Programmer
Programmer
Posts: 20
Joined: Mon Jun 12, 2006 4:08 pm
Contact:

additional code i just did

Post by Vaptor » Fri Oct 10, 2008 7:05 am

// by vaptor
// numbers are limited to 23 digits
// strings are long enough to work with this
//
// storage formats
//
// item ID - howmany,
//for error prevention look for the dash also so we don't pick a amount by accident
//
// issue can't seem to pin down a method that won't be a lag causeing dissassembly if i use strings
//
// work around i can use 2 or more sets of int variables. Int values are integer numbers in the range -2147483648 to 2147483647, in other words signed 32 bit values.
//

class ItemManager extends object Abstract;

//////
////////////////////////////////////////////////////////////////////////////////

var class< WeaponModifier > EffectClasses[54]; // template for the default list

struct ArtifactInventory
{
var int itemset1;
var int itemset2;
var int itemset3;
var int itemset4;
var int itemset5;
var int itemset6;
};

Static function Class<WeaponModifier> TranslateITEM(int itemposition, ArtifactInventory Playerinv)
{
local int hold;
local Class<WeaponModifier> selecteditem;

//main conversion to get the class
// decide which item set has what the user selected and hold on to that
Hold=class'itemmanager'.static.Howmany(itemposition,playerinv);
// get the classtype
selecteditem=class'itemmanager'.static.Convert(Itemposition);
if(hold > 0)
{
Return selecteditem;
}

return(Class'noWeaponModifier'); // only give this if theres 0 of it
}

// howmany function is probly going to be used on the hud so its seperated here

static function int Howmany(int itemposition, ArtifactInventory Playerinv)
{
local float casehack,posthack;
local int typehack,tophack; // dissasemble the number in a way that avoids problems
local int finalhack;
local int holding; //contains the inventory set
local int realpos;
if (itemposition < 11)
{
holding=Playerinv.itemset1;
realpos=itemposition - 1;
}
else if (itemposition < 21)
{
holding=Playerinv.itemset2;
realpos= itemposition - 11;
}
else if (itemposition < 31)
{
holding=Playerinv.itemset3;
realpos= itemposition - 21;
}
else if (itemposition < 41)
{
holding=Playerinv.itemset4;
realpos= itemposition - 31;
}
else if (itemposition < 51)
{
holding=Playerinv.itemset5;
realpos= itemposition - 41;
}
else
{
holding=Playerinv.itemset6;
realpos= itemposition - 51;
}

//useing only 9 of 10 numbers for realpos allows me to get away with this
if(realpos > 0)
{
casehack=holding*(10^-realpos); //type is the number in the tens digit rando is the ones
}
else
{
casehack=holding;
}
realpos+=1; //add one on to move past the desired value

posthack=holding*(10^-realpos);

//now remove the top after reduceing
tophack=int(casehack);
typehack=int(casehack); // now it should remove numbers after the decimal (works)

finalhack=(typehack-(tophack*10)); //get the single digit for this item
Return Finalhack; // this is the single digit number result
}
// get the class from a stored array , this can not be a config entry must be present in compile
// items in position 10 , 20 ,30 ,40 and 50 must not exceed 2 else the entire system might get rounded

Static Function Class<WeaponModifier> Convert(int ItemID)
{
//todo return the correct class for the powerup effect functions change the number in the database to the class containing effect code
if(ItemID > -1)
{
Return (Default.Effectclasses[ItemID] ); // keep the list of powerup classes in this file due to restrictions that cause static functions to be prohibited from reading data that is not present at compile time and limited to defaults when its not replicated
}
else
{
return 0; //if a error happened we get this
}
}
////////////////////////////////////////////////////////////////////////////////
//current weapon changes will include holding the powerups as a definded interger array with members matching the class array defined in this class
// mostly purpose of this class is to act as a handler for communication between a weapon of power and weapon modifiers
// makes up for not actually keeping the object this way we can fake the items in the inventory list and reduce chances players will get the get crashes from powerup count after we revise it
//rpgstat revision i have in mind will show the weapon modifers that have a value of 1 or higher on the list of useable items
//
////////////////////////////////////////////////////////////////////////////////


//=====================================================================
// function does most everything like appling poision damage or knock back and even healing effects to
//=====================================================================

Static function GetEffectforitem(weaponofpower CurrentWeapon, int itemnumber,int powerlevel, Optional Pawn Victim) // useing optional will not throw errors if the effect does not do damage dies before this runs for any reason
{
if(currentweapon != none)
{
if(itemnumber > -1) // it should never be -1 if it is something is not working correctly
{
//process effects is a function that has a vital role we use converttoclass to get the file that does the effect of the powerup in question this is executed instead to replace sorting though the inventory over and over for the same effects , so this works faster with less cpu
if(victim == none)
{
currentWeapon.ProcessEffects(class'itemmanager'.static.(itemnumber),powerlevel); // this effect has no victim
}
else
{ // note: currentweapon is the Weapon of power in use that has acess to the rpg alterations and the holder of the weapon

CurrentWeapon.ProcessEffects(convertToclass(itemnumber),powerlevel,Victim); // both functions execute the effect code directly in the weaponofpower itself makes it easyer to acess ingame stuff from there. point of execution might need to be changed from the weapon only if it dosen't work out for some unexpected reason.
}
}
}

}

//=======================================================================================
// the third function is just to do adding powerups and checking should be done in the weapon of power but new functions need added there
//
// class'weaponofpower' is the child of class'rpgweapon' just to remind you which class Needs new code
//
// function ChangeModifier(int Powerup_ID,int mode)
// {
// Switch(mode) // mode 0 is add item to effect list
//
// }
//=======================================================================================
static function int ResetWeaponslots(Rpgstatsinv ActiveRpgdata, weaponofpower currentWeapon, ArtifactInventory Playerinv)
{
if(ActiveRpgdata != none) // found the datastorage actor that rpg uses to keep the ingame active player data , also used for send recieve of commands that require client involvement at some point
{
// CRAP this is a problem but current method is just as costly requires me to break down and compare how many player has on weapon and how many in inventory plus chuck out any extra that go over inventory limitations
// notice item old based inventory has this bug also it often will hold more in inventory when they unloaded a weapon than they are allowed to pickup
}
}
static function bool addtoweapon( Rpgstatsinv ActiveRpgdata, weaponofpower currentWeapon, int itemfromList)
{
if(ActiveRpgdata != none) // found the datastorage actor that rpg uses to keep the ingame active player data , also used for send recieve of commands that require client involvement at some point
{
if(ActiveRpgdata.haswopitem(Itemfromlist)) // use rpgstatsinv on the local player to check if he actually has any of that item stored as data only
{

if(currentweapon != none) //safeguard against lag
{
if(currentWeapon.HasSpaceforitem(Itemfromlist) ) // check if weapon has empty slots and if the powerup is allowed include checks for similar powerups that prevent use of others. for superspeed powerup we can't allow another speed powerup
{
currentWeapon.changemodifier(ItemFromList,0); // tell the weaponofpower class that holds powerup data to add this item to its active effects list that we need to add

Return True; // make sure to subtract 1 from this item in inventory
}
else
{
Return False; // nope can't add the item by returning false we can use this function to trigger a message also if we want to saying can't add to weapon
}
}
}

Return False;
}
////////////////////////////////////////////////////////////////////////////////
// some examples class'poisionmodifier' is by no means a valid name it probly needs packages too in the name
//=========================
defaultproperties
{
Effectclasses[0]=class'PoisionModifier'
Effectclasses[1]=class'PoisionModifier'
Effectclasses[2]=class'PoisionModifier'
Effectclasses[3]=class'PoisionModifier'
Effectclasses[4]=class'PoisionModifier'
Effectclasses[5]=class'PoisionModifier'
Effectclasses[6]=class'PoisionModifier'
Effectclasses[7]=class'PoisionModifier'
Effectclasses[8]=class'PoisionModifier'
Effectclasses[9]=class'PoisionModifier'
Effectclasses[10]=class'PoisionModifier'
Effectclasses[11]=class'PoisionModifier'
Effectclasses[12]=class'PoisionModifier'
Effectclasses[13]=class'PoisionModifier'
Effectclasses[14]=class'PoisionModifier'
Effectclasses[15]=class'PoisionModifier'
Effectclasses[16]=class'PoisionModifier'
Effectclasses[17]=class'PoisionModifier'
Effectclasses[18]=class'PoisionModifier'
Effectclasses[19]=class'PoisionModifier'
Effectclasses[20]=class'PoisionModifier'
Effectclasses[21]=class'PoisionModifier'
Effectclasses[22]=class'PoisionModifier'
Effectclasses[23]=class'PoisionModifier'
Effectclasses[24]=class'PoisionModifier'
Effectclasses[25]=class'PoisionModifier'
Effectclasses[26]=class'PoisionModifier'
Effectclasses[27]=class'PoisionModifier'
Effectclasses[28]=class'PoisionModifier'
Effectclasses[29]=class'PoisionModifier'
Effectclasses[30]=class'PoisionModifier'
Effectclasses[31]=class'PoisionModifier'
Effectclasses[32]=class'PoisionModifier'
Effectclasses[33]=class'PoisionModifier'
Effectclasses[34]=class'PoisionModifier'
Effectclasses[35]=class'PoisionModifier'
Effectclasses[36]=class'PoisionModifier'
Effectclasses[37]=class'PoisionModifier'
Effectclasses[38]=class'PoisionModifier'
Effectclasses[39]=class'PoisionModifier'
Effectclasses[40]=class'PoisionModifier'
Effectclasses[41]=class'PoisionModifier'
Effectclasses[42]=class'PoisionModifier'
Effectclasses[43]=class'PoisionModifier'
Effectclasses[44]=class'PoisionModifier'
Effectclasses[45]=class'PoisionModifier'
Effectclasses[46]=class'PoisionModifier'
Effectclasses[47]=class'PoisionModifier'
Effectclasses[48]=class'PoisionModifier'
Effectclasses[49]=class'PoisionModifier'
Effectclasses[50]=class'PoisionModifier'
Effectclasses[51]=class'PoisionModifier'
Effectclasses[52]=class'PoisionModifier'
Effectclasses[53]=class'PoisionModifier'
Effectclasses[54]=class'PoisionModifier'
Effectclasses[55]=class'PoisionModifier'
Effectclasses[56]=class'PoisionModifier'
Effectclasses[57]=class'PoisionModifier'
Effectclasses[58]=class'PoisionModifier'
Effectclasses[59]=class'PoisionModifier'
Configuration= //still needs one

}

Post Reply

Return to “Mod/Mutator Development”