Mystra's development thread

Discussion in 'Development General' started by Mystra, Aug 10, 2010.

Thread Status:
Not open for further replies.
  1. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    I had trainers as pokemon idea (do not use IE here) recently and reading A question about server-side I though of trying to make it so it is easier to add additional non-standard pokemon.

    I have a couple a questions before I'll start however. If anyone has answers you are welcomed here (^. ^)

    1. It seems currently data is saved as line number = pokemon number. However some files has more probably lines due to forms. Is that so?

    2. I think to make it easier and with less changed I should make it so all files of one type are read first then PO will handle them like it normally do.

    Like say read db/pokes/4G_level_moves.txt. Append db_custom/pokes/4G_level_moves.txt to it in memory and then handle it like normal.

    However it seems that'll clash with future official pokemon numbers that will be released.

    I though of adding them as less than 0 numbers. -1, -2, -3, however it may cause many changes in code, since code itself probably (don't sure yet) assumes base 0.

    The other way is using high number like, say, base 100.000 however reading some files in db/ made me believe it's already used for forms (base 1000?).

    The other way is to make additional pokemon separate from standard. However this will require more changes in code and I'm note sure is it possible to do without much hassle. Some flag in pokemon struct maybe? (and numerous code snipets to check for it...) I'm thinking about trying this way.

    Any ideas?
     
  2. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    1. It seems currently data is saved as line number = pokemon number. However some files has more probably lines due to forms. Is that so?

    Forms that are purely aesthetic will have high numbers (1000+) but no appearance in other files, except specific files like form_descriptions.

    Forms that have new things (like Shaymin-S: new typing, new move, or rotom formes, ...) have a number following the other pokémons, without gap. That means when gen 5 will be out, there'll probably be a compatibility break because those pokémons will be pushed further.

    2.

    I think a file describing the changes from the regular database files could be used. For example, each server could have a MOD file to give to download (later it'd just give the MD5 of the mod file, and the client would download it only if it hasn't the MOD file in memory). Maybe do that in a human readable way, or use diff files (like SVN or GIT), ... That would be up to you =)

    Concerning the code, maybe the database will be reloaded each time a MOD file is loaded. For that, you'd need to reset the DB and call init() again. And find a way to init on some modded files instead of the base files. Or you could init on the base files and then apply the changes...
     
  3. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Thank you (^. ^)

    So much code… I should wrap my mind around it (^ ^) Don't mind me if I'm posting some simplistic snippets here, it's easier to have it in one place.

    Hmm… It seems all general pokemon data is PokeGeneral class. So…

    Code (text):
    1.  
    2. class PokeGeneral
    3. {
    4. protected:
    5.     bool customPokemonFlag;
    6. public:
    7.  
    8.     PokeGeneral(const bool customPokemon = false);
    9.     bool isCustom(void);
    10. }
    11.  
    Code (text):
    1.  
    2. PokeGeneral::PokeGeneral(const bool customPokemon)
    3. {
    4.     this->customPokemonFlag = customPokemon;
    5. }
    6.  
    7. bool PokeGeneral::isCustom(void)
    8. {
    9.     return customPokemonFlag;
    10. }
    11.  
    Let's see where is info loading…
     
    Last edited: Aug 11, 2010
  4. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Code (text):
    1. : git push origin mystra
    2. fatal: The remote end hung up unexpectedly
    Hmm… It seems I forgot something or it is not possible yet :) Well, there is nothing to commit yet, so it does not matter for now.
     
  5. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    You need to set a different connection for developper access.

    Aka, edit .git/config to add the line pushurl="ssh://seremel@pogeymon-online.git.sourceforge.net/gitroot/pogeymon-online/pogeymon-online" under url="...."

    Also, if you want me to add comments to any source file, don't hesitate.
     
  6. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Oh, yeah, thank you (^ ^)'

    I tried to commit and push that code above to test it as I'll probably need this anyway (it compiles and seems to run). If everything went right it should be there in mystra branch (^ ^)

    BTW should I ask questions in this thread or is it better with PMs/emails/whatever for you? Of course since I'm pretty new in this project I may have many questions so you don't need to answer right away as you see them. Only when you have time.
     
  7. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Well, in this thread, or on the server, or on #po on irc.freenode.net. Sometimes on the server i'm not in the main channel, so you may have to find me =). But whatever is fine.
     
  8. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Hmm... it looks weird a bit in qgit now… i.e. my line shows as black. It was the other way around before. Have I messed up something or is that how it is supposed to look? My Git skills suck (~_~)

    http://img62.imageshack.us/img62/1733/37448663.png

    (X_X)
     
    Last edited: Aug 11, 2010
  9. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    I tried adding custom field to some info classed and got the feeling I'm doing it wrong. Too bad PokemonInfo class is singleton. Maybe I should change it to be normal class first... Otherwise I will need to duplicate every field and change every method there. Ouch... Are there any hidden pitfalls that cause this to be undesirable?
     
  10. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    well

    if you want to update your branch, go on your branch and do:

    Code (text):
    1. git merge devel
    or

    Code (text):
    1. git merge master
    Whichever branch you want to merge.

    If you have any conflicts during the merge, you can go back, or you can do

    Code (text):
    1. git mergetool
    To fix the files. It uses meld by default, and it's pretty cool. Once you've fixed the files do git add <filenames> and then git commit to finish the merge. If you have a problem remembering which files need merging, use git status.

    It took time also for me to adapt, but once you know how it works it's easy =D

    Also, if you only want to pick a certain commit from another branch, do git cherry-pick <commit-id>
     
  11. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    I will not use it for now. That would be better... Can you please look if I reverted your commits just now (can I even do that? at least I tried to drop last 2 commits from my branch) and push them again if need? Damn, I'm scared of this thing (@_@) Hopefully it changed only locally. Well, check it just in case.
     
  12. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    About PokemonInfo, it's true i didn't think about it much, but you could duplicate every field with a name indicating it's a duplicated field. Then make the PokemonInfo class keep in memory a static instance of itself, which would actually be initialized in PokemonInfo::init().

    Or, what I'd do, is reload the whole database with the changes everytime you change your MOD files. Because there is no reason to keep in memory the differences between databases? Then the only thing you'd have to change is the init function, so that they also use the other files. MODDed files can be full files or just diffs, as you want. And then calls to init() would clear the database in memory and reload it.

    I'm sorry for this a bit messy state of things, i know singleton the way i did them are not really good, but it did not cause any problems until now.
    And don't worry, if you stay in your branch nothing will happen to mine. And if you do stupid stuff, the sourceforge repository won't revert anyway. I'll take a look though.
     
  13. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    I checked, and nothing wrong ^^
     
  14. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Well, I tried a way of duplicating every field it's time consuming and prone to errors in the future if changes will be needed. What I want to do is something like this:

    Code (text):
    1.  
    2. namespace AllData {
    3.     PokemonInfo info(); // normal
    4.     PokemonInfo info_custom(true); // custom. Or whatever params were there.
    5. }
    6.  
    On the other hand I'll need to change previous PokemonInfo::*() calls to AllData::info.*() calls.

    Why I want to do it is… I don't want to change existing database. I want to add pokemon to it. I.e. I'm not going to do all the thing suggested in that thread. I want to have new non-standard Pokemon, that's all. I.e. there is no differences between DBs as at it is normal DB + extended part. But at the same time I don't want it to break with future generation update, so they should be separate. Should I not go this route?

    Yay (^ ^)'
     
  15. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Hmm... maybe I should go your route after all… Or mine version with add files in memory and then process them. They'll change custom to new ones when new standard ones will be released but it's not that ground breaking, they were non-standard anyway. Hmm... I'll think again (^ ^)
     
  16. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
  17. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    So, will not touch server part for now. The idea is as follows:

    1. Extension DB need only files that will add to db/pokes content (in memory only). All other files in db/ are irrelevant.

    2. I need to read all init() and call everything there twice. Once with normal parameters and once with custom flag.

    3. It seems fill_container_with_file() which is heavily used there _adds_ to container (which is good). I.e. there is no need to do anything with it and it still should work.

    4. Instead of adding flag to every pokemon it would be better to make a function which will calculate if the pokenum is > than last standard pokemon.

    Then something about the server can be done, I guess. Hopefully it is as easy as it sound.
     
    Last edited: Aug 11, 2010
  18. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Ok, I made PokemonInfo::init_worker() and moved some code from init() there:

    Code (text):
    1.  
    2. void PokemonInfo::init(const QString &dir)
    3. {
    4.     /* makes sure it isn't already initialized */
    5.     if (NumberOfPokemons() != 0)
    6.         return;
    7.  
    8.     m_Directory = dir;
    9.     m_Directory_custom = "custom_" + m_Directory;
    10.  
    11.     QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    12.     QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    13.  
    14.     init_worker(false);
    15.  
    16.     // save last standard pokemon number. TODO: add "- 1"?
    17.     lastStandardPokeNum = TrueCount(); // OR NumberOfPokemons()?
    18.  
    19.     init_worker(true);
    20. }
    21.  
    22. void PokemonInfo::init_worker(const bool customPokemon)
    23. {
    24.     loadNames(customPokemon);
    25.     loadFormes(customPokemon);
    26.     loadEvos(customPokemon);
    27.     loadMoves(customPokemon);
    28.     fill_container_with_file(m_Type1, path("poke_type1.txt", customPokemon));
    29.     fill_container_with_file(m_Type2, path("poke_type2.txt", customPokemon));
    30.     fill_container_with_file(m_Genders, path("poke_gender.txt", customPokemon));
    31.     fill_container_with_file(m_Ability1, path("poke_ability.txt", customPokemon));
    32.     fill_container_with_file(m_Ability2, path("poke_ability2.txt", customPokemon));
    33.     fill_container_with_file(m_LevelBalance, path("level_balance.txt", customPokemon));
    34.     loadBaseStats(customPokemon);
    35. }
    36.  
    Now loadFormes(), loadEvos(), and loadMoves() seems to operate on indexes and uses line numbers taken from a file. Since I read 2 files I'll need to add a modifier to this (0 based every time). Am I thinking right that for instance in PokemonInfo::loadFormes(true) I should do:

    Code (text):
    1.  
    2. int shift = customPokemon ? lastStandardPokeNum : 0;
    3.  
    ? And add it to all indexes when it is about m_AestheticFormes[], m_AestheticFormesHidden[], and m_AestheticFormesDescs[]?

    i.e. those hashes use pokenum as "index" (key)?
     
    Last edited: Aug 11, 2010
  19. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    I think m_AestheticFormes[] and m_AestheticFormesHidden[] use the base number of the pokémon as the index. But , for m_AestheticFormesDescs, it just uses the forme number, as each forme has a different desc (i.e forme name). And the forme number is something like 10XX.

    So yes you could add the shift modifier to m_AestheticFormes and m_AestheticFormesHidden, but for m_AestheticFormesDescs it's a different story (maybe add another 1000 to it? But then you would need to also add 1000 to the begin/end of the pair contained in m_AestheticFormes for non standard pokémons).

    When I think about it, I hope the merge of our 2 branches will go alright as i also make some changes for gens. i.e. I'll also have a container for 3rd gen abilities, and items. But i won't edit pokémons so it should be cool.

    Edit: I did most of my changes in pokemoninfo and pokemonstructs, and in the teambuilder. So you can assume that PokemonInfo as it is now is safe.
     
    Last edited: Aug 12, 2010
  20. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    I'm getting Rotom-C instead of (one) new pokemon after Arceus in Team builder. Now I'm sure those forms and formes were created for this only reason to annoy me with unexpected results (X_x)
     
  21. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    You'll probably laught but I made something completely different (^__^)\

    Adds to server script an ability to change type chart!

    scriptengine.h (class ScriptEngine : public QObject):
    Code (text):
    1.  
    2. public:
    3.     Q_INVOKABLE void modifyTypeChart(int type_attack, int type_defend, int value);
    4.  
    scriptengine.cpp
    Code (text):
    1.  
    2. void ScriptEngine::modifyTypeChart(int type_attack, int type_defend, int value)
    3. {
    4.     TypeInfo::modifyTypeChart(type_attack, type_defend, value);
    5. }
    6.  
    pokemoninfo.h (class TypeInfo)
    Code (text):
    1.  
    2. public:
    3.     static void modifyTypeChart(int type_attack, int type_defend, int value);
    4.  
    pokemoninfo.cpp
    Code (text):
    1.  
    2. void TypeInfo::modifyTypeChart(int type_attack, int type_defend, int value)
    3. {
    4.     m_TypeVsType[type_attack * NumberOfTypes() + type_defend] = value;
    5. }
    6.  
    sample usage:
    Code (text):
    1.  
    2. ({
    3.  
    4. serverStartUp : function() {
    5.     sys.modifyTypeChart(6, 13, 2); // Bug -> Psychic = x1
    6. },
    7.  
    8. afterLogIn : function(source) {
    9.     sys.sendMessage(source, "This server uses modified type chart!");
    10. }
    11.  
    12. })
    13.  
    Now, do we have constant for types available for scripts? Don't think there are for multiplier values though.

    Hmm... Do we need this in our scripts? I think it's nice to have but that's up to you :)

    I have not updated my branch with this yet. How do I drop my branch and all changed and create it anew anyway? Can you do that? I don't wont to touch it even with 10ft pole (^ ^)'
     
    Last edited: Aug 12, 2010
  22. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    It's alright, you can push the type chart!

    to drop the changes, revert back to the one commit you want and do "git checkout". If you want to delete the branch, try git branch -d <branch name>. I'll do that on the online git repository too if you want.

    For the formes, this is annoying, you'd need to load the normal DB first, then insert the custom pokémons before the formes. Then rotom will have as an alternate forme your first Custom Pokemon, but you can deal with this later (you'll need to change that part of the db too).

    Or, you could completely change the way data is stored in the PokemonInfo class...

    Tbh, i don't think PokeGeneral needs a customFlag, i mean, if you change the database, then all pokémons are normal pokémons, aren't they?
     
  23. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Yeah, flag is not needed. However function to check for this is, since it need to know from where to load resources (different folders). Or maybe change it to check both locations - no flag needed.

    The more I do it the more I think it is counterproductive to do like that. At least I don't like the final result of it. I'll try to modify PokemonInfo too maybe to see how far this goes.

    Hmm... I'll try to revert changes and make checkout. I'll make new clone first to be sure.
     
  24. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    It... accepted? Really? (O_O) I learned git revert in process (@_@) Check my branch when you have time. I merged master (I think) to it before doing my changes. 2 reverts should undo my previous custom stuff. New commit should have only what I've written above. If not - something is not right.

    Should compile and work. I think I need to add constants for easier use later (TYPE_GRASS, DAMAGE_DOUBLE, etc.). Is it possible to do?
     
    Last edited: Aug 12, 2010
  25. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    There's tons of constants already, in pokemonstructs.h

    Type::Grass, Type::Normal, ...

    I don't see what you mean by DAMAGE_DOUBLE.

    I'll check the changes and post here if there's a problem!
     
  26. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    I mean do they accessible to scripts? As for damage it is value that specifies how much damage it takes. Like double damage, half damage, no damage. Or is it there already?
     
  27. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Oh, ok.

    For damage , i think you can return the raw damage.

    0, 0.5, 1, or 2

    For types, you can create 2 functions: type(id), and typeNum(typename), like there is with natures/moves/abilities/pokemons. Or you can do the constants, i'm curious how you would do that, but you'd still need to provide the type() and typeNum() functions.

    By the way the update went well =)
     
  28. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Isn't it is 0, 1, 2, and 4 internally?

    \(^. ^)/

    As for constants... Even though they do exist in QtScript I couldn't managed it to work for some reason (O.o)
     
    Last edited: Aug 12, 2010
  29. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Isn't it is 0, 1, 2, and 4 internally? -> Yes =). But scripters would only see 0, 0.5, 1, 2 as this is something internal.
     
  30. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Umm... my code assumes it is those numbers. Giving them 0, 0.5, 1, and 2 will make them believe anything is good while it is not. Maybe changes there are needed then. Or, maybe, a function like damageMultiplier() with "effective", "ineffective", "none", "normal" parameters which returns one of those?

    Code (text):
    1.  
    2. QString ScriptEngine::type(int id)
    3. {
    4.     QString res = "Unknown type";
    5.     QString names[] = {
    6.         "Normal", "Fighting", "Flying", "Poison", "Ground", "Rock",
    7.         "Bug", "Ghost", "Steel", "Fire", "Water", "Grass", "Electric",
    8.         "Psychic", "Ice", "Dragon", "Dark", "Curse"
    9.     };
    10.     if((id >= 0) && (id < 18)) res = names[id];
    11.     return res;
    12. }
    13.  
    14. int ScriptEngine::typeNum(const QString &typeName)
    15. {
    16.     int res = -1;
    17.     QString compare_to = typeName.toLower();
    18.     QString names[] = {
    19.         "normal", "fighting", "flying", "poison", "ground", "rock",
    20.         "bug", "ghost", "steel", "fire", "water", "grass", "electric",
    21.         "psychic", "ice", "dragon", "dark", "curse"
    22.     };
    23.     int i = 0;
    24.     while((i < 18) && (names[i] != compare_to)) i++;
    25.     if(i < 18) res = i;
    26.     return res;
    27. }
    28.  
    Hmm... Is it ok code? (^ ^)
     
    Last edited: Aug 13, 2010
  31. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Use TypeInfo::Name(num), and TypeInfo::Number(type) ^^

    Look at ScriptEngine::moveNum:

    Code (text):
    1.  
    2. QScriptValue ScriptEngine::moveNum(const QString &name)
    3. {
    4.     int num = MoveInfo::Number(convertToSerebiiName(name));
    5.     return num == 0 ? myengine.undefinedValue() : num;
    6. }
    (The convertToSerebiiName is used to solve case problems)

    And for the type mod, you can do:
    Code (text):
    1.  
    2. void ScriptEngine::modifyTypeChart(int type_attack, int type_defend, float value)
    3. {
    4.     /* Hack to safely transform a float into an int, even with rounding precision problems */
    5.     TypeInfo::modifyTypeChart(type_attack, type_defend, int(2*value+0.01f));
    6. }
     
  32. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    (^ ^)'
     
  33. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Code (text):
    1. int(2*value+0.01f)
    BTW and if someone writes something like 4 there, what happens?

    I don't like the hack with rounding and all... Maybe I'll make it a string after all?
     
  34. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Then the attack is 4 times as effective... lol. You can check that the converted value is between 0 and 4 if you want.

    value = std::min(4, std::max(0, value));
     
  35. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Is those numbers are used like that? I though since it says enum whatever then it compares to it and not use as is. No? (O.o)
     
  36. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    There's no enum for type efficiency. ^^
     
  37. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Really? I must sleep then (^ ^)' I prefer my idea with a string parameter. If you are not against it I'll do it. I don't want hacks. They always bite you somewhere in the end (~_~)
     
  38. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Mmm okay. No problems.
     
  39. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Pushed to my branch.

    Documentation:

    type(id): returns type's display name.
    typeNum(typeName): returns type's id.
    modifyTypeChart(attackerTypeId, defenderTypeId, modifier): will modify type chart for server. modifier must be one of the following strings: "none", "ineffective", "normal", "effective".

    Example of usage:
    Code (text):
    1. sys.modifyTypeChart(sys.typeNum("bug"), sys.typeNum("psychic"), "normal");
    This code causes Bug attacks to do normal damage to Psychic type pokemon.
     
  40. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    168
    Alrighty, merged.
     
Thread Status:
Not open for further replies.