ID:155619
 
Allo..

So yea ive been trying to findle around with my skilltree system and i have been using const variables to hold an ID for the skills.

But due to this i cant use the usual generic way of doing a list which would be list(testskill1 = 3) where 3 meaning it needs level 3 of testskill1 before allowing the next skill to be unlocked.

So the only other option that comes to mind is doing something like..

Skillreq = list(test1, test2)
skillreqlev = list(3,1)

where skillreqlev denotes the level required for each of the skillreq's corresponding position

I remember seeing this in a dev post somewhere and i cant seem to remember the posters name so i cant go back to it unfortunately.

If anyone is able to give me a response to this it would be appreciated.

~Midget
You're method would work, but you can also do list("[test1]" = 3,"[test2]" = 1) if you're more used to associative lists.

If you want to try the other way, you just need to find the index of your skill (you can use list.Find() for this if you aren't already looping through the list by an index). Alternatively, if your IDs are sequential and start at 1, you can just have the one list of levels, and use the skill ID as the index.

Really, though, it sounds like you're making unnecessary work for yourself by referring to skills with a number. Why not use a datum?
In response to DarkCampainger
var/const
//test Skills
TESTSKILL1 = 00001
TESTPASSIVE1 = 00002
TESTSKILL2 = 00003
TESTPASSIVE2 = 00004
TESTSKILL3 = 00005
TESTPASSIVE3 = 00006

skill
parent_type = /obj

var
element
id
cooldown = 0
casttime = 0
level = 1
max = 5
uses
list/itemreqs
list/link
current_cooldown = 0


//and a small outtake from the skilltree displayer..
mob/human
proc
refresh_skillcoats()
for(var/skilltree/theskill in world)
if(theskill.overlays) overlays = null
client.images -= theskill.img_maxed
client.images -= theskill.img_autogain
client.images -= theskill.img_locked
client.images -= theskill.img_available

var/shown_screen = 0
var/checked = 0

if(!checked && !shown_screen)
var/hasreqs = 1

if(hasreqs && theskill.skillreqs)
for(var/required in theskill.skillreqs)
if(!HasSkill(required))
hasreqs = 0
world << "DBG.. [theskill.name] has hitten no match @ skillcheck"
break
else //this is where im working atm. its meant to check against the level
//of a skill inside the players skill list. which needs an additional loop which is easy and ive done elsewhere just not placed here yet.
world << "DBG.. [theskill.name] has hitten no match @ skillcheck on level req "
hasreqs = 0
break

//and for sake of reference.
mob/human/proc
HasSkill(id)
for(var/skill/skill in skills)
if(skill.id == id)
return 1
return 0


What is the method that your suggesting?

EDIT:: You're method would work, but you can also do list("[test1]" = 3,"[test2]" = 1) if you're more used to associative lists.
Returns:: Codes\S. Skills - SkillTree.dm:557:error: : expected a constant expression
In response to Midgetbuster
Midgetbuster wrote:
> //...
>

What is the method that your suggesting?

EDIT:: You're method would work, but you can also do list("[test1]" = 3,"[test2]" = 1) if you're more used to associative lists.
Returns:: Codes\S. Skills - SkillTree.dm:557:error: : expected a constant expression

Oops, forgot to mention that you can't do it at compile time. You'll have to stick the list's creation in world/New() or something.

Also, looking at that code, you really don't seem to be benefiting from using those IDs. You might as well use the skill's type.

If you use the type, you could also take advantage of locate():
mob/human/proc
HasSkill(skillType)
return (locate(skillType)!=null)
In response to DarkCampainger
Yea i was thinking of redoing the entire skilltree and skill code.

That was done awhile back and i havn't really changed it or even looked into it as of late until me and the co decided to start iconning some of the skilltree and skill icons before coding in the actions of the skills. so it made me look into it more.

So you reckon just dump the ID var, and use skilltypes directly?. (also means dumping the const vars). And what method would you suggest for some form of quickhand so that when defining a large amount it could be easily found (similar to that of const where i can just Search the source for say.. testskill1 for any reference of it)

and HasSkill is used alot to locate the skill inside the player. use for obtaining and leveling up skills as a final check to ensure no lil nasties get through aswell as for the displaying of the "sheet" over icons to display locked/available and so on. (thats what the small snippet of refresh_skillcoats() was. one part of many checks for displaying one of 5 sheets)
In response to Midgetbuster
Midgetbuster wrote:
So you reckon just dump the ID var, and use skilltypes directly?. (also means dumping the const vars). And what method would you suggest for some form of quickhand so that when defining a large amount it could be easily found (similar to that of const where i can just Search the source for say.. testskill1 for any reference of it)

I would say so. You can just think of the type as a sort of ID. You didn't appear to be doing any numerical arithmetic with the IDs, so there's really no point in keeping track of a huge list of constants when you have the type variable right there.

Also, as in my example in my previous post, locate() would be a quick way to get a reference to their skill object matching a specific type (assuming you only include types in the skill list that have no child types). If it returns null, then they don't have it. Otherwise, you now have a reference to the skill object.
In response to DarkCampainger
Also, as in my example in my previous post, locate() would be a quick way to get a reference to their skill object matching a specific type (assuming you only include types in the skill list that have no child types). If it returns null, then they don't have it. Otherwise, you now have a reference to the skill object.

When i use this it always appears to return a skill. Which as you stated is a reference to the object.

But it always returns even if they don't have the skill in there skill list. (which is opposite to what you stated it would do)

mob/human
verb
DBG99Typtest()
if(HassSkill(/skill/testskills/TesterSkill1))
world << "Has Skill."
else
world << "Does not Have skill."

mob/human/proc
HassSkill(skillType)
if(locate(skillType))
world << "Located Skilltype."
else
world << "Could not Locate"
return (locate(skillType)!=null)


This is what comes back on having an empty skill list. (or should be empty its a fresh character)

DBG1..
Located Skilltype.
Has Skill.

Now add the skill..

Dbg2..
Located Skilltype.
Has Skill.

Same result on both..

Maybe i misread the information given as something else but unsure if i did or not
In response to Midgetbuster
Midgetbuster wrote:
When i use this it always appears to return a skill. Which as you stated is a reference to the object.

But it always returns even if they don't have the skill in there skill list. (which is opposite to what you stated it would do)

Whoops, my mistake. It's been a long day. I forgot to specify which list to search, so it's searching everywhere. Try this:

mob/human/proc
HassSkill(skillType)
var/skill/S = locate(skillType) in src.skills
if(S)
world << "Located Skilltype."
else
world << "Could not Locate"
return (S!=null)
In response to DarkCampainger
Repost. With edits to avoid double post spam

i thought it was something like that.

i removed the !=null part of the return as just returning the skill is fine and helps to null another proc. With or without it, it returns the same results or atleast it seems to.

Just another couple of questions they have arisen.

Would you happen to have any thoughts on doing a shorter form for adding the references to lists? if not its cool just curious :p.
As it stands i still use a variable inside the "skilltree" datum so that it knows what skill to add so i have to do /skill/teststuff/testone in that variable to link it. as opposed to the old form (using const vars) TESTONE which would assign a numeric number to it and as such do searching procs to find matching ids.
--==--
The next question imposed is i have an Add Skill verb for admins and for debugging purposes that adds a skill i previously could do this just by inputting the numeric ID of the skill and allowing it to run its searches. Now with the removal of Const vars i can no longer do this.. Instead i have to somehow type in the path of the skill.
I find that this could be a hassle and instead tried looking into making a list of all the types so that you can choose it. the list becomes big as you would think and includes all the sub directories such as /skill/fire then /skill/fire/fireball for example. when i don't really need to see /skill or even /skill/fire since there not actual skills naturally.

I also tried just having a "text" input on the verb but typing in the skill name does not get me the skill, while trying to use Locate(). i even tried typing the full path into the text field so /skill/test/testone which also could not locate the skill. but if add the path to a list inside the .dm file it works fine, despite both being outputted the exact same when viewing the list. which kinda stumps me, since im trying to find an efficient way to add skills for debugging purposes without having to do the usual skilltree procedure.

In response to Midgetbuster
Midgetbuster wrote:
Repost. With edits to avoid double post spam

i thought it was something like that.

i removed the !=null part of the return as just returning the skill is fine and helps to null another proc. With or without it, it returns the same results or atleast it seems to.

So long as you properly use boolean conditionals (if(HassSkill(t)) instead of if(HassSkill(t)==1), and if(!HassSkill(t)) instead of if(HassSkill(t)==0)) it should work fine. And as you said, can double for getting a reference to the actual skill object.

Just another couple of questions they have arisen.

Would you happen to have any thoughts on doing a shorter form for adding the references to lists? if not its cool just curious :p.
As it stands i still use a variable inside the "skilltree" datum so that it knows what skill to add so i have to do /skill/teststuff/testone in that variable to link it. as opposed to the old form (using const vars) TESTONE which would assign a numeric number to it and as such do searching procs to find matching ids.

One option would be to just enter a text string containing the last portion of the path, and then have the skilltrees automatically convert that to a real path in New(). You'll have to be careful that no skill names overlap, though. It would probably be best to seed an associative list at world/New() where "name" = type_path, so the skill trees can do a quick lookup of the type.


The next question imposed is i have an Add Skill verb for admins and for debugging purposes that adds a skill i previously could do this just by inputting the numeric ID of the skill and allowing it to run its searches. Now with the removal of Const vars i can no longer do this.. Instead i have to somehow type in the path of the skill.
I find that this could be a hassle and instead tried looking into making a list of all the types so that you can choose it. the list becomes big as you would think and includes all the sub directories such as /skill/fire then /skill/fire/fireball for example. when i don't really need to see /skill or even /skill/fire since there not actual skills naturally.

If you create the associative list I mentioned above, you could always let them pick from that. As to weeding out the parent types and only including types without children, check out this handy snippet:
Nulliparous Type Paths

I also tried just having a "text" input on the verb but typing in the skill name does not get me the skill, while trying to use Locate(). i even tried typing the full path into the text field so /skill/test/testone which also could not locate the skill. but if add the path to a list inside the .dm file it works fine, despite both being outputted the exact same when viewing the list. which kinda stumps me, since im trying to find an efficient way to add skills for debugging purposes without having to do the usual skilltree procedure.

Although they appear the same when output as text, a type path and a text string are two very different values. However, you can convert a properly formatted text string to a type path with text2path()


Here's how I would suggest setting all of that up:

// Associative list where text string of last portion of path = type path
// eg "Fire_ball" = /skill/elemental/Fire_ball
var/list/skill_paths = list()

// Generate the skill_paths list, seeding it with path "names" and their associated type path value.
proc/prepareSkillPaths()
var
finalSlash
i
nodeName
pathName

for(var/path in nulliparae(/skill/))
pathName = "[path]"
i=0

// Search the path text string for the last '/'
do
finalSlash = i
i = findtext(pathName, "/", i+1)
while(i)

// Copy the text after the last '/', which we'll treat as the name
nodeName = copytext(pathName, finalSlash+1)

// Add the node to the list
skill_paths[nodeName] = path

world/New()
..()
prepareSkillPaths()



skilltree
var/list/skillreqs

New()
// Swap out the text names with the actual paths from the skill_paths list
for(var/i = 1 to skillreqs.len)
skillreqs[i] = skill_paths[skillreqs[i]]

.=..()


/////////// Test code


PathOfTheSamurai
skillreqs = list("Impale","Bleed")




skill
elemental
Fire_ball
swordplay
Impale
Bleed

mob
var/skilltree/skillTree = new/skilltree/PathOfTheSamurai()
Login()
for(var/A in skillTree.skillreqs)
world<<"[A] (ispath()=[ispath(A)])"
world<<"----------"
for(var/A in skill_paths)
world<<"[A] = [skill_paths[A]]"
..()




// Title: Nulliparous Type Paths
// Credit to: Jtgibson
// Contributed by: Jtgibson
// http://www.byond.com/members/Jtgibson/forum?id=232#232

// Returns 1 if the specified parameter is nulliparous, 0 otherwise.
proc/nulliparous(type)
var/tmp/list/types = typesof(type); return (types.len == 1)


// Returns a list of all of the nulliparous types derived from the
// given type path (excluding the type itself).
proc/nulliparae(type)
var/list/types = typesof(type) - type; . = list()
for(var/nutype in types) if(nulliparous(nutype)) . += nutype


I'll let you figure out choosing one of the names from list and creating the associated path :)
In response to DarkCampainger
Arr thanks for that.

I had a bit of confusion for a minute i was like. how the hell is that working then i actually looked through it all instead of reading it like a book.

Thats quite nifty. Thanks for helping out. can improve on this nicely now