| 07-26-2007, 08:09 PM | #1 |
It's really a basic system, but I thought I'd submit it anyways. What it does: Reverses Blizzard's EXP system (More heroes = less XP) and flips it to (More heroes = More XP). It also allows you to control the amount of EXP granted, and what units in the radius are checked for and given XP (These work off the same real, but if requested I can make them independent, so that you can check for heroes in, say, 1000, and only grant the XP to heroes in 600) What else can it do? It can be reversed back to Blizzard's method (More heroes = less XP) while still retaining the ability to edit the radius of effect and XP amounts granted. It also allows you to give heroes less XP if they're farther away. Also supports XP splitting. Why I made it: My map, Wolf Packs, is obviously a pack-orientated game. However, soloing would allow you to level up far faster than packs. So, to counter this, I made this system. Makes sense doesn't it? Also, it was a shitload easier to use than changing Blizzard's constants. What it can be used for: Games like mine that emphasize pack/group/team behavior, or RPG's even. If you can find a use for it, go right ahead. The Code JASS:scope DEXP initializer Init //Configuration globals globals private constant real RADIUS = 650. //Radius to consider heroes for exp gain private constant real CLOSE = 200. //Determines "Close" for distance effect. Gives full exp private constant real MEDIUM = 400. //Determines the "Middle" for distance effect. Gives less exp private constant real FAR = 650. //Determines the "Far" for distance effect. Gives even less exp //Should probably be the same as Radius. private constant real CLOSE_FACTOR = 1. //Determines what % of exp heroes in the "close" range get. (1 == 100%) private constant real MEDIUM_FACTOR = .5 //Determines what % of exp heroes in the "medium" range get. (.5 == 50%) private constant real FAR_FACTOR = .25 //Determines what % of exp heroes in the "far" range get. (.25 == 25%) private constant integer UNIT_EXP = 10 //How much exp per level (of the unit) units give. private constant integer HERO_EXP = 15 //How much exp per level (of the dying hero) heroes give. private constant integer BONUS_EXP = 9 //How much exp is granted per allies hero nearby. //If this value is positive, more heroes == more exp each //if this value is negative, more heroes == less exp each ('Blizzard' method) //If this value is 0, the number of heroes effects nothing. //This is for the displaying of exp in textag format private constant real DURATION = 5. //How long the message will last private constant integer SIZE = 12 //Font size private constant integer RED = 0 //Red value (of 255) for the text private constant integer GREEN = 74 //Green value (of 255) for the text private constant integer BLUE = 255 //Blue value (of 255) for the text private constant boolean SHOW_TEXT = true //Set this to false to stop texttags private constant boolean SPLIT = false //Set to true to divide the final exp by the number of heroes private constant boolean DISTANCE_EFFECT = true //Set to false if you do not want the //distance from the kill to determine how much exp the heroes get. endglobals private constant function Formula takes integer XPfactor, integer unitlevel, integer heroesinradius, integer bonus returns integer return (XPfactor * unitlevel) + (heroesinradius * bonus) //This is the function that determines how XP is calculted. //Unless you have a different method, don't touch this. endfunction //This is the filter that picks up heroes in the radius of the killer. //To modify it, simply add more booleans. private function filter takes nothing returns boolean local unit u = GetFilterUnit() local boolean b1 = IsUnitType(u, UNIT_TYPE_DEAD) == false local boolean b2 = IsUnitType(u, UNIT_TYPE_HERO) == true local boolean b3 = IsUnitAlly(u, GetOwningPlayer(GetKillingUnit())) == true set u = null return b1 and b2 and b3 endfunction //Use this filter to modify the exp given for certain conditions. private function ExpFilter takes integer exp, unit u returns integer return exp endfunction //This applies the XP accordingly. private function GiveXP takes nothing returns nothing local unit u = GetDyingUnit() local unit f local unit Killer = GetKillingUnit() local player p = GetOwningPlayer(Killer) local integer add local integer KilledUnitLevel local integer unitNum = 0 local group g = CreateGroup() local real x = GetUnitX(Killer) local real y = GetUnitY(Killer) local real distance set bj_groupCountUnits = 0 call GroupEnumUnitsInRange(g, x, y, RADIUS, Condition(function filter)) call ForGroup(g, function CountUnitsInGroupEnum) set unitNum = bj_groupCountUnits //============================================================ if IsUnitAlly(u, p) == false then if IsUnitType(u, UNIT_TYPE_HERO) == true then set KilledUnitLevel = GetHeroLevel(u) set add = Formula(HERO_EXP, KilledUnitLevel, unitNum, BONUS_EXP) else set KilledUnitLevel = GetUnitLevel(u) set add = Formula(UNIT_EXP, KilledUnitLevel, unitNum, BONUS_EXP) endif endif if SPLIT then set add = R2I(add / unitNum) endif //============================================================ if DISTANCE_EFFECT then set add = ExpFilter(add, u) loop set f = FirstOfGroup(g) exitwhen f == null set distance = ((GetUnitX(Killer)-GetUnitX(f)) * (GetUnitX(Killer)-GetUnitX(f))) + ((GetUnitY(Killer)-GetUnitY(f)) * (GetUnitY(Killer)-GetUnitY(f))) //Far Away Units if distance > MEDIUM*MEDIUM and distance <= FAR*FAR then call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) set add = R2I(add * FAR_FACTOR) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00) //Medium Distance Units elseif distance > CLOSE*CLOSE and distance <= MEDIUM*MEDIUM then call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) set add = R2I(add * MEDIUM_FACTOR) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00) //Close Range Units elseif distance <= CLOSE*CLOSE then call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) set add = R2I(add * CLOSE_FACTOR) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00) endif if SHOW_TEXT and add > 0 then call CreateTextTagEX("+ " + I2S(add), SIZE, f, DURATION, RED, GREEN, BLUE) endif call GroupRemoveUnit(g, f) endloop else set add = ExpFilter(add, u) loop set f = FirstOfGroup(g) exitwhen f == null if SHOW_TEXT and add > 0 then call CreateTextTagEX("+ " + I2S(add), SIZE, f, DURATION, RED, GREEN, BLUE) endif call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00) call GroupRemoveUnit(g, f) endloop endif call DestroyGroup(g) set g = null set u = null set Killer = null set f = null endfunction //This trigger stops players from gaining XP when they shouldn't be. private function Cut_XP_Gain takes nothing returns nothing local integer i = 0 loop exitwhen i > 12 call SetPlayerHandicapXP(Player(i), 0.00) set i = i + 1 endloop call DestroyTimer(GetExpiredTimer()) endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger t = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH ) call TriggerAddAction(t, function GiveXP ) call TimerStart(CreateTimer(), .04, false, function Cut_XP_Gain) set t = null endfunction endscope The Demo Map:Let your heroes kill. Look for the following:
Implementing The System: All instructions for doing so are inside the demo map. System Requirements: The ability to read and understand basic instructions The ability to change numbers and words NOTE: This requires JassNewGenPack to use the vJASS version. It's nothing different except vJASSified. Old version still in map with all the new features. No extra stuff (NewGenJASS, grimoire, WEU, CScache, etc.) are needed. But NewGen will make your life easier =D Code:
Changelog -v1.9. Lied again! Fixed a problem with the test map not working, as well as made the texttags show up even when using range-determined exp. Thanks Zaraf for discovering the bug. -v1.8: I lied, new version. Now has a filter for the dying unit (to modify exp), texttag support, and some tweaks. Plus a vJASS version. -v1.7: Probably the final version. Merged the 2 triggers and tweaked minor details. Thanks for the help Moyack! -v1.6: Optimized and tweaked the code a bit. -v1.5: Added even more features and optimized the code. -v1.4: Added 2 new features and fixed any leftover indentation slop. -v1.3: Indented the code the conformist way. (Looks no different to me, but whatever) -v1.2: Optimized the code more. (thanks PipeDream and Pyrogasm!) -v1.1: Changed some tiny stuff involving my loops and if's (thanks Ammorth and Pyrogasm!) -v1.0: I made the system. Nothing special. Credits: Darkwulfv (me) - I made the system. W00t. Pyrogasm - He read my code, checked it, and made the sexy image you see down below Rising_Dusk - He gave me the idea to do the system, and answered some questions I had. PipeDream - He forced me to indent my code, so he gets credit for some reason. The_Elite - He suggested hero XP splitting according to distance from the kill. (Which i used) Moyack - He merged my 2 triggers and did other minor touch-ups. Thanks! Zaraf - Discovered that the test map doesn't work (minor errors on my part). -Enjoy! If you feel I need to add more information, let me know and I'll get right on it. |
| 07-27-2007, 07:01 AM | #3 |
Few things. Change: JASS:set f = FirstOfGroup(allies) loop exitwhen f == null call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(p, 0.00) call GroupRemoveUnit(allies, f) set f = FirstOfGroup(allies) endloop JASS:loop set f = FirstOfGroup(allies) exitwhen f == null call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(p, 0.00) call GroupRemoveUnit(allies, f) endloop endfunction Don't use count units in group. Just add 1 to the integer variable as you add the units to the group. Otherwise nice system; simple and effective. |
| 07-27-2007, 07:08 AM | #4 | |
Thanks for spotting that. I'm still not perfect with JASS, but I think I did a good job. I'll replace all the code accordingly and update the map. Quote:
|
| 07-27-2007, 07:20 AM | #5 |
|
| 07-27-2007, 07:34 AM | #6 | |
Quote:
|
| 07-27-2007, 07:40 AM | #7 |
Seems most of these can be done only with game constants |
| 07-27-2007, 07:55 AM | #8 |
True, but game constants are a hassle to sort through. Also, this gives you more control and better handling. Lemme ask you. Which would you rather do? Sort through all of Blizzard's hero experience constants and change each and every one to your needs, or change ~4 values in a couple keystrokes? If you read, you'd also know it's reversable, so you can go make it like Blizzard's system, but with more control. PipeDream, I have rewhatevered my system, it's more optimized now. The initial function (the action for the core) was there because of an earlier method I was using, before I discovered it could be changed. The code is now fixed and ready for another review. Thanks =D |
| 07-27-2007, 04:20 PM | #9 |
There are many exp related constants that make manually editing Blizzard's exp system very difficult, so I can see the reason behind this system, however, I have no use for it. |
| 07-27-2007, 05:15 PM | #10 | |
Quote:
He stubbornly refuses, pretending somehow that his method is the best or whatever. -_-; |
| 07-27-2007, 05:20 PM | #11 | |
Quote:
|
| 07-27-2007, 05:31 PM | #12 |
But when you submit it as a resource, it no longer matters what is best for the submitter, but for those who might use it. That's the whole point, because this level of indenting is terrible for what now matters. |
| 07-27-2007, 05:39 PM | #13 | |
Rawr to all those who hate my indenting. It makes sense to me at least. If you're all so against it, someone's gonna have to tell me how the hell to "fix" it, because nobody ever told me the "standard" method. I taught myself to indent. If someone tells me, then maybe I'll be a little more willing to fix it, rather than everyone just saying "Your indent sucks fixfixfix". If I knew the quote-unquote "standard" method, do you think I'd still be doing it like this? (Even though it makes perfect sense to me). Quote:
You know the old phrase "You can lead a horse to water but you can't make it drink?" It's the same concept here, except you're all assuming I know the way to the water and you're dunking my head in it. I'm only semi-defending my indentation methods since that's how I learned and have always done it. But if someone shows me the "standards", by all means I'll fix it. |
| 07-27-2007, 06:45 PM | #14 |
It's rather simple. Everything inside the same block is indented one level deeper than stuff outside the block. With blocks i mean stuff between function - endfunction, loop - endloop, globals - endglobals, if/else - endif That especially means that locals, set and call are not at different levels of indentation when they`re in the same block. Fix: JASS://This applies the XP accordingly. function DES_GiveXP takes nothing returns nothing local unit u = GetDyingUnit() // etc... loop set f = FirstOfGroup(g) exitwhen f == null if IsUnitAlly(f, p) and IsUnitType(f, UNIT_TYPE_HERO) == true then call GroupAddUnit(allies, f) set unitNum = unitNum + 1 endif call GroupRemoveUnit(g, f) endloop // etc. .... loop set f = FirstOfGroup(allies) exitwhen f == null call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) call AddHeroXP(f, add, true) call SetPlayerHandicapXP(p, 0.00) call GroupRemoveUnit(allies, f) endloop call DestroyGroup(g) call DestroyGroup(allies) set u = null set Killer = null set f = null endfunction I mean, how does the following make sense? JASS:set f = FirstOfGroup(allies) loop exitwhen f == null call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00) call AddHeroXP(f, add, true) The number of spaces per level of indentation doesn't really matter, I've used 2 in the example but it should be equal for all levels. And I agree with everyone else in the thread that sane indentation is a vital part of jass systems. |
| 07-27-2007, 07:26 PM | #15 |
I generally use 4 between levels for my code, but it doesn't really matter as long as it's consistent. Otherwise I agree with everything Pitzer mentioned. |
