|
Mods Everything about mods |
|
Thread Tools | Display Modes |
#1
|
|||
|
|||
Modding Tutorial - Adding an Ability to Apply after a Unit's Attack
Okay, I've finally gotten to a point where I can fight Bone Dragons and so have had a chance to work on improving them.
So I thought this would be a great opportunity to provide a mini LUA scripting tutorial about how to add the capability of a post-hit affect to a unit. Note that this post is very long and you are encouraged to take your time reading it and visit the references provided here and duplicated at the end of this post: LUA Documentation (note that King's Bounty uses LUA version 5.0) King's Bounty Libraries Translated to English So let's clearly state what we want to do:
The first file to edit is BONEDRAGON.ATOM: Code:
main { class=chesspiece receiver=bones model { 0=bonedragon.bma 1=bonedragondeath.bma } cullcat=0 bboxanim=1 } arena_params { features_label=cpi_bonedragon_feat features_hints=undead_header/undead_hint,bone_header/bone_hint,flies_header/flies_hint posthitslave=features_bone_creature race=undead cost=3200 level=5 leadership=1300 attack=43 defense=43 defenseup=6 initiative=6 speed=7 hitpoint=600 krit=10 hitback=1 hitbackprotect=0 movetype=2 attacks=moveattack,poison_cloud features=bone,undead,dragon resistances { physical=0 poison=50 magic=0 fire=0 } moveattack { ad_factor=1 usefly=4 damage { poison=50,65 } custom_params { poison=0 } } . . . (file continues...)
We basically only need to do a couple of things to this file to enable a new post-attack ability: Add: posthitmaster=script_name Add: new features header and hint to the features_hints= item so that people can see the new ability. For the file above, look at the start of the arena_params {...} section and you'll see where the features_hints= item starts (repeated here): Code:
. . . arena_params { features_label=cpi_bonedragon_feat features_hints=undead_header/undead_hint,bone_header/bone_hint,flies_header/flies_hint posthitslave=features_bone_creature . . . Code:
. . . arena_params { features_label=cpi_bonedragon_feat features_hints=undead_header/undead_hint,bone_header/bone_hint,flies_header/flies_hint,bonedragon_attack_header/bonedragon_attack_hint posthitslave=features_bone_creature . . . The next thing we need to do is add the capability of the unit to be able to call a script when performing its attack. To enable this ability, we need to add a posthitmaster=script_name to the arena_params {...} section. I'm not sure if it matters where you add this so long as it is in the arena_params {...} section, but I usually add it just before the resistances section since that's where I've seen it mostly placed (you can always search on posthitmaster= to see if a script already exists for that ATOM with your text editor). Once again, you need to think of what you want to call your script, once again, this is an internal name that you are going to use. I'm just going to call my new script: features_bonedragon_attack. Here is the implementation in the ATOM: Code:
. . . features=bone,undead,dragon posthitmaster=features_bonedragon_attack resistances { physical=0 poison=50 magic=0 fire=0 } . . . The next part we need to work on is the script. You could create a new LUA file with your new script in it if you wish or edit an existing file. In the case here, most of the unit features are included in the UNIT_FEATURES.LUA script. So we're going to add the posthitmaster script to this file, the name of the function must be the same name as script_name identified with posthitmaster= - in this case the function name must be called features_bonedragon_attack. This function is shown in the code block below and I'll go through each section. I added this to the top of UNIT_FEATURES.LUA, but you can add it anywhere to that file so long as it is outside any other function block: Code:
-- New function for adding a bonus to % of chance to inflict an effect function effect_chance( value, effect_or_feature, kind ) local bonus = tonumber( Logic.hero_lu_item( "sp_chance_" .. effect_or_feature .. "_" .. kind, "count" ) ) if bonus ~= nil then value = value + bonus end return value end -- New Bone Dragon Attack function features_bonedragon_attack( damage, addrage, attacker, receiver, minmax ) if ( minmax == 0 ) then local receiver_level = Attack.act_level( receiver ) local receiver_chance = ( 5 - receiver_level ) * 25 local rnd = Game.Random( 100 ) local poison = tonumber( Attack.get_custom_param( "poison" ) ) if rnd < receiver_chance and damage > 0 and poison == 0 and not Attack.act_feature( receiver, "magic_immunitet" ) and not Attack.act_feature( receiver, "golem" ) and not Attack.act_feature( receiver, "pawn" ) and not Attack.act_feature( receiver, "boss" ) then local tmp_spells = {} if not Attack.act_is_spell( receiver, "spell_scare" ) and not Attack.act_feature( receiver, "mind_immunitet" ) and not Attack.act_feature( receiver, "undead" ) then table.insert( tmp_spells, spell_scare_attack ) end if not Attack.act_is_spell( receiver, "spell_plague" ) and not Attack.act_feature( receiver, "demon" ) and not Attack.act_feature( receiver, "plant" ) then table.insert( tmp_spells, spell_plague_attack ) end if not Attack.act_is_spell( receiver, "spell_weakness" ) and not Attack.act_feature( receiver, "plant" ) and not Attack.act_feature( receiver, "undead" ) then table.insert( tmp_spells, spell_weakness_attack ) end if not Attack.act_is_spell( receiver, "spell_crue_fate" ) and Attack.act_name( receiver ) ~= "vampire2" then table.insert( tmp_spells, spell_crue_fate_attack ) end if not Attack.act_is_spell( receiver, "spell_ram" ) and not Attack.act_feature( receiver, "plant" ) and not Attack.act_feature( receiver, "undead" ) then table.insert( tmp_spells, spell_ram_attack ) end if not Attack.act_is_spell( receiver, "effect_curse" ) and not Attack.act_feature( receiver, "plant" ) and not Attack.act_feature( receiver, "undead" ) then table.insert( tmp_spells, effect_curse_attack ) end if table.getn( tmp_spells ) > 0 then Attack.act_aseq( 0, "cast" ) local dmgts = Attack.aseq_time( 0, "x" ) local cast = Game.Random( 1, table.getn( tmp_spells ) ) local spell_level = 3 if tmp_spells[ cast ] == spell_plague_attack then tmp_spells[ cast ]( receiver, spell_level, dmgts ) elseif tmp_spells[ cast ] == effect_curse_attack then tmp_spells[ cast ]( receiver, 1, 3 ) else tmp_spells[ cast ]( spell_level, dmgts, receiver ) end Attack.log_label( '' ) end end end return damage, addrage end -- New Ent Entangle function features_entangle( damage, addrage, attacker, receiver, minmax ) . . . (file continues) Code:
-- New Bone Dragon Attack function features_bonedragon_attack( damage, addrage, attacker, receiver, minmax ) . . . For this function, the argument list is:
Code:
. . . if ( minmax == 0 ) then . . . end Let's continue: Code:
. . . local receiver_level = Attack.act_level( receiver ) local receiver_chance = ( 5 - receiver_level ) * 25 local rnd = Game.Random( 100 ) local poison = tonumber( Attack.get_custom_param( "poison" ) ) . . . You can see here that this code block gets the level of the receiving unit (reference the King's Bounty library) and computes the chance of the effect based on a formula. Next it uses another King's Bounty library to generate a random number and lastly gets a custom parameter from the attacking unit's ATOM file. Next is another if statement to check if the unit is to have the posthitmaster effect applied: Code:
. . . if rnd < receiver_chance and damage > 0 and poison == 0 and not Attack.act_feature( receiver, "magic_immunitet" ) and not Attack.act_feature( receiver, "golem" ) and not Attack.act_feature( receiver, "pawn" ) and not Attack.act_feature( receiver, "boss" ) then . . . end All the other checks have to do with checking to make sure that the receiving unit does not have a certain feature. Let's continue with the next code section: Code:
. . . local tmp_spells = {} if not Attack.act_is_spell( receiver, "spell_scare" ) and not Attack.act_feature( receiver, "mind_immunitet" ) and not Attack.act_feature( receiver, "undead" ) then table.insert( tmp_spells, spell_scare_attack ) end . . . The Code:
local tmp_spells = {} The if statement uses a King's Bounty library to check to see if the receiver allready has the Fear spell. Note that the code name for the Fear spell is used: spell_scare. Once again there are more checks to see if that spell can be cast on that unit and then the last statement table.insert inserts the name into the tmp_spells table. It is important to note here that the value inserted is an actual function name for the spell: spell_scare_attack. This is the actual function call for the Fear spell when you cast this spell from your spellbook. I had a little bit of difficulty grasping this when I was learning LUA, but you can see it is very powerful in that you can create a list of functions you want to call or a list of possible functions that you want to call. The next code sections are checking for similar spells with their appropriate function names, and you'll note the last one is not a spell but an effect: Code:
. . . if not Attack.act_is_spell( receiver, "effect_curse" ) and not Attack.act_feature( receiver, "plant" ) and not Attack.act_feature( receiver, "undead" ) then table.insert( tmp_spells, effect_curse_attack ) end . . . The next section of code: Code:
. . . if table.getn( tmp_spells ) > 0 then . . . end . . . Next is the code inside the check to select an effect to apply and then apply it: Code:
. . . Attack.act_aseq( 0, "cast" ) local dmgts = Attack.aseq_time( 0, "x" ) local cast = Game.Random( 1, table.getn( tmp_spells ) ) local spell_level = 3 . . . Code:
Attack.act_aseq The next section of code: Code:
. . . if tmp_spells[ cast ] == spell_plague_attack then tmp_spells[ cast ]( receiver, spell_level, dmgts ) elseif tmp_spells[ cast ] == effect_curse_attack then tmp_spells[ cast ]( receiver, 1, 3 ) else tmp_spells[ cast ]( spell_level, dmgts, receiver ) end . . . Code:
tmp_spells[ cast ] The next part of the statement includes a parameter list in (). So let's say that Code:
tmp_spells[ cast ] Code:
spell_scare_attack( spell_level, dmgts, receiver ) You can see here that this is very powerful in that you can make a table of function calls and call one randomly, or in sequence, etc. The important point to note is that you can distinguish from the various functions with an if statement and create a customized argument list for each function. Think about this and let it sink in some more. The next statement: Code:
. . . Attack.log_label( '' ) . . . The last portion of code in this function is: Code:
. . . end end end return damage, addrage end . . . Okay, this is probably a lot to digest, but let it sink in a bit and re-read it if you'd like before continuing. Normally at this point you'd probably be complete, but in this case we still have a little more work to do. Note that we're calling some spells from within this function. So we need to ensure that the calls will work for the spells we're trying to call. So for the next file we need to edit is to find where such functions as spell_scare_attack, etc. exist and make sure that we have a compatible argument list and see if the spell will work as is. The function spell_scare_attack (and pretty much all spell function calls) is located in SPELLS.LUA. Let's go to the code for the spell_scare_attack: Code:
. . . -- *********************************************** -- * Scare -- *********************************************** function spell_scare_attack( lvl, dmgts ) if dmgts == nil then dmgts = 0 end local target = Attack.get_target() if ( target ~= nil ) then local level = common_get_spell_level( lvl ) local ehero_level if Attack.act_belligerent() == 4 then ehero_level, level = get_enemy_hero_stuff( level ) end local duration = int_dur( "spell_scare", level, "sp_duration_scare" ) Attack.act_del_spell( target, "effect_fear" ) Attack.act_apply_spell_begin( target, "effect_fear", duration, false ) Attack.act_apply_par_spell("autofight", 1, 0, 0, duration, false) Attack.act_apply_spell_end() Attack.atom_spawn(target, 0, "magic_scare", Attack.angleto(target)) Attack.act_damage_addlog(target,"add_blog_fear_") end return true end . . . There is also this statement: Code:
local target = Attack.get_target() Code:
. . . function spell_scare_attack( lvl, dmgts, target ) if dmgts == nil then dmgts = 0 end if target == nil then target = Attack.get_target() end. . . Note how we changed the Code:
local target... Code:
Attack.get_target() What you'll notice here is that by adding the new parameter, target, to the end of the function argument list, we're not changing any other function calls that used only the first two arguments (lvl and dmgts) and by checking if target is not assigned before assigning it to Code:
Attack.get_target() This is a pretty advanced concept and I want you to think about it for a bit. The spell_scare_attack function may have other calls and we want to ensure that we don't "break" it by our changes. The changes above allow the existing function to work with our new features_bonedragon_attack function call while maintaining its ability to work with all previous function calls. In some cases, it may not be possible to alter an existing function call to work with a new way of calling it. In that case you'd have to make a new function (based on the old one preferably) to handle the different way that you want to use it. So you just have to be careful (and I've gone through this a lot) to make sure that you don't break anything existing when changing it. You'll notice that if you go through the AP / CW LUA files that they simply created new functions for the Witch Hunter positive spell effects rather than use existing ones and try to alter them. I prefer to try to use the existing one whenever possible since it eliminates redundant code which may be changed in one place but not the other if you decide to change how a function works; however, from a validated code viewpoint (for quality assurance) you may not want to change code that you've already validated because then you have to re-validate it. The rest of the code, I'm going to leave as an exercise for you to study the LUA documentation and King's Bounty libraries to figure out how it works. The last file we need to change goes back to the changes we made to the ATOM file. Remember that we added new features_hints= values? We now need to add what those descriptions are. For unit features, they are located in ENG_UNIT_FEATURES.LNG (or your equivalent local language file). Here is a code snippet: Code:
. . . cpi_vampire_feat=Undead, Regeneraion, No retaliation. cpi_vampire2_feat=Undead, Regeneraion, No retaliation, Death's Deception. cpi_bat_feat=Undead, Soaring, No retaliation, Drain Life. cpi_zombie_feat=Undead. cpi_zombie2_feat=Undead, Decay. cpi_archer_feat=Undead, Archer, Bone. cpi_skeleton_feat=Undead, Bone. cpi_bonedragon_feat=Undead, Bone, Flight. cpi_ghost_feat=Undead, Soaring, Phantom, Soul Draining. cpi_ghost2_feat=Undead, Soaring, Phantom, Soul Draining. cpi_blackknight_feat=Undead, Steel Armor, Dark Commander, Rising Anger. cpi_necromant_feat=Undead, Cloud of Darkness. . . . Code:
. . . cpi_bonedragon_feat=Undead, Bone, Flight. . . . So then add it to the comma-separated list of abilities like so: Code:
. . . cpi_bonedragon_feat=Undead, Bone, Flight, Chaos. . . . So here's a code snippet: Code:
// ÃÂÃÂÃÂÃÂâì dead_evasion_header=^def_hint_t0^Death's Deception dead_evasion_hint=^def_hint_t1^Avoids critical attacks by vanishing in the shadows. undead_header=^def_hint_t0^Undead undead_hint=^def_hint_t1^Being raised from the dead has the following features:<br>50% Poison Protection<br>+50% Attack during nighttime and underground combat.<br>+1 to Morale if combat takes place in the cemetery.<br>Takes 200% of damage from Holy Attacks.<br>Immune to Mind spells and some other spells. vampirism_header=^def_hint_t0^Drain Life vampirism_hint=^def_hint_t1^Sucks a part of the health points from its enemy, recovering his own health. Dead creatures arise. feature_name_header=^def_hint_t0^Header Name feature_name_hint=^def_hint_t1^Description Hint Where feature_name is the name of your feature. In our case it is called bonedragon_attack. The ^def_hint_t0^ and ^def_hint_t1^ are template names located inside TEMPLATES.LNG (note that this file name is the same for all localizations). Templates are codes that you can use for using a color, a label, calling a function to generate a value, etc. When you see the various colors in the text descriptions, they are using colors specified in the template name. You'll also see where you may have a common description (i.e. like Defense: ) so you can make labels with common names and refer to their shorthand template name if it is identified in the template. Let's look at ^def_hint_t0^ for example in TEMPLATES.LNG: Code:
. . . def_hint_t0=<shadow=off><align=center><font=ft1_14><color=255,243,179>$ // ÓÌÅÍÈß // Ïîäïèñü â îêíå ãåðîÿ skills_tl=<align=center><color=0,0,0><font=ft1_12>$ skills_t0=<align=center><font=ft1_12><gen=skill_caption><gen=skill_name> skills_tN=$ skills_tN { closed=<color=20,147,182> open=<color=255,243,179> } . . .
Code:
skills_tl=<align=center><color=0,0,0><font=ft1_12>$ This is just the tip of the iceberg and talking about templates is a whole other guide topic. So let's get back to adding our Bone Dragon's Chaos ability header and hint: Code:
. . . // ÃÂÃÂÃÂÃÂâì // New! Bone Dragon's Chaos bonedragon_attack_header=^def_hint_t0^Chaos bonedragon_attack_hint=^def_hint_t1^Casts a random Chaos Spell or Effect (Fear, Plague, Weakness, Doom, Sheep, or Curse) on the target (if applicable) when attacking. Chance to cast the spell is +25% for each level the unit is below the Bone Dragon's (i.e. level 1 = 100%, level 4 = 25%). The power of the spell is affected by the hero's spell power if the Bone Dragon is lead by one and casts the spell at third level. dead_evasion_header=^def_hint_t0^Death's Deception dead_evasion_hint=^def_hint_t1^Avoids critical attacks by vanishing in the shadows. . . . So that's it! You can now save and close ENG_UNITS_FEATURES.LNG and the other files that you edited and place them into your mods folder. The next step is to debug your code by running King's Bounty in Development mode. There are plenty of posts that describe how to do that, but it is encouraged to always debug new code you create to help minimize errors and make sure it works! In making the changes above, when I initially created the features_bone_dragon_attack function, I did not realize that I had to check to make sure that it was the Bone Dragon's main attack. So at first, the Bone Dragon's main attack and Poison Cloud would cause the effect to be applied. So to limit it to just the main attack I needed to add the check for poison == 0, which is in the Bone Dragon's custom parameters for its main attack. Also note that you might want to specify the base percent chance to the ATOM and allow for people to change it. I actually may end up implementing it that way, but if you did you'd do this: For BONEDRAGON.ATOM: Code:
. . . moveattack { ad_factor=1 usefly=4 damage { poison=50,65 } custom_params { poison=0 chance=20 } } . . . Next UNIT_FEATURES.LUA: Code:
local receiver_level = Attack.act_level( receiver ) local chance = tonumber( Attack.get_custom_param( "chance" ) ) local receiver_chance = ( 5 - receiver_level ) * chance local rnd = Game.Random( 100 ) local poison = tonumber( Attack.get_custom_param( "poison" ) ) Lastly, ENG_UNITS_FEATURES.LNG: Code:
. . . // ÃÂÃÂÃÂÃÂâì // New! Bone Dragon's Chaos bonedragon_attack_header=^def_hint_t0^Chaos bonedragon_attack_hint=^def_hint_t1^Casts a random Chaos Spell or Effect (Fear, Plague, Weakness, Doom, Sheep, or Curse) on the target (if applicable) when attacking. Chance to cast the spell is +20% for each level the unit is below the Bone Dragon's (i.e. level 1 = 80%, level 4 = 20%). The power of the spell is affected by the hero's spell power if the Bone Dragon is lead by one and casts the spell at third level. . . . Then if in the future you decide to change it, you just have to change BONEDRAGON.ATOM and ENG_UNITS_FEATURES.LNG - both are text files, which are a little bit easier for people to edit and makes the change more mod friendly. Please take a while to review what I've written here and I'm hoping to do more of these tutorials / guides as time permits. Here are the references again that I mentioned above: LUA Documentation (note that King's Bounty uses LUA version 5.0) King's Bounty Libraries Translated to English Feel free to ask any questions you'd like if you don't understand anything about this post - and good luck! /C\/C\ |
#2
|
|||
|
|||
Ok, this cosmetic a unit.
But what can i do, if i want to walk around my army with a for cycle? I think something like this: for i=1 to 5 do writeln army[1].name name, buffs, defences, etcetera Ok, Au.name(unit); but where the hell specify the "unit" Or what can i do, if i want to show a multitext on screen, with the return values of my function? Pls, if its possible, and you know, help me at least with a small suggestion, or some lines code. |
#3
|
|||
|
|||
I'll try...
I'm not quite sure what you're asking, but I'll try to help you...
Quote:
By the way, is English your first language? If not, then we may be running into an issue where you have a slightly different vocabulary than mine - you'll probably have to get me up to speed on what you mean... By the way, if you speak Russion, the Russian developers frequent the Russian forums and they answer questions directly... Quote:
Quote:
By the way, are you intested in modding The Legend (TL), Armored Princess (AP), Crossworlds (CW), Warriors of the North (WotN), or all of them? Do you understand LUA? By the way, the WotN Bug Fixes Thread serves as a mini-tutorial on changing sections of the LUA code to fix problems - that is a great start to get small bits of code to study... If you can cite some specific code examples in specific files that you don't understand, I (or others) may be able to help you. Also let me know what your goals are (i.e. add new features, change units, make a campaign, etc.). If you have patience and time, you should be able to understand how the code works and start making changes... /C\/C\ |
#4
|
|||
|
|||
Sorry for my poor english; and i dont speak Russian.
Thx for advices, but im afraid, my goals impossible. I will try to express myself more accurately, example: I want to unit resistances should always visible on dlg_chesspiece, in new lines, not only hint. It is possible? And if yes, how? I tried many ways, and failed. Logic....() is not enough. Cant fix hint as simple_text. Resistances available with Au....(unit); but the unit parameter how works? Can i set a unit from hero army? The best solution would be a new, own script. I studied game and mod files, i see the relationships, and i can write some scripts, but this task not feasible for me. In warcraft3 editor, i was able to accomplish pickpocketing five minutes with triggers. 5 years ago, when programming was chinese for me. Code sipmply, logical; events, objects clearly. Easy to display my own textboxes with custom texts. Easy to insert my own models and textures. And great documentation with examples. Now i have experienced with delphi (+minimal javascript, actionscript, php knowledge). Lua syntax not too much of a problem; but kings bounty scripting very strange, and im afraid, very limited. And documentations not available or incomplete. |
#5
|
|||
|
|||
Give this a try...
Quote:
Quote:
I think the files you need to start with are: 1) ENG_UNITS.LNG (or your equivalent LNG files) and 2) TEMPLATES.LNG. At the top of ENG_UNITS.LNG, you'll see where the text descriptions of the abilities are (i.e. you'll see such labels as CPI_LEADERSHIP, CPI_ATTACK, etc. (note that I've capitalized them here so they standout, but they are lower case in my LNG file)). Then you'll see equals (=) and usually a template surrounded by the caret, i.e. ^int_cpi_t0^. Such templates are in TEMPLATES.LNG (search in there for that template) and essentially serve as keywords for a "macro" that can do many different things to display text such as change the color, display a text string, run an LUA function, etc. Now if you compare the unit cards between TL and WotN, you'll notice that Crit has been added and the unit's Current Health removed from the unit card. Now what you want to do is add more lines to the the unit card. For this, I think the files you need to edit are DLG_CHESSPIECE.UI and INFO_CHESSPIECE.UI. From your other posts, I can see that you've been modding the UI files pretty extensively and so I think you already know how to edit these files. As far as I can tell, DLG_... is used for outside of the arena and INFO_... is used inside the arena (i.e. when you are not and are fighting battles, respectively). For all the "begin simple text" statements, the text strings should be in the *.LNG files. For example, "cpi_initiative2" is in ENG_UNITS.LNG. You probably know a lot more about the UI files than I do, but there are other text strings (for example "text_15" or all the "text_##" strings for that matter) that I don't know where they are. Now if you want to add the resistances, you need to look at the [res] macro under the cpi_defense_h label (in ENG_UNITS.LNG) using the def_hint_t1 template with the res macro (these are located in TEMPLATES.LNG): gen=gen_unit_res. This refers to the gen_unit_res function located in TEXTGEN.LUA. What you probably want to do, since you want the resistances to be spelled out separately, is you're going to want to create variants of that function (i.e. gen_unit_res_physical, ..._astral, ..._fire, etc.) that simply list a value for one resistance type that display the resistance values (as well as the base values). You'll then want to add the lines to display new text lines to the UI files and you can add the new labels to either ENG_UNIT.LNG or your can make a new LNG file with your new labels. After that, you need to edit the picture of the dialogue to extend its space, but I think you already know how to do this. I think that is pretty much it - hopefully I've been clear and if not ask more questions! Quote:
TL TEXTGEN.LUA (lines 121-136): Code:
function gen_unit_res(data) local text="" local res_count=AU.rescount() for i=0,res_count-2 do local res = AU.resistance( data, i ) local t="" if res>95 then res=95 end if res> 0 then t="<label=cpi_defense_res_D>" end if res< 0 then t="<label=cpi_defense_res_U>" end text=text.."<br> -<label=cpi_defense_res_"..(i+1)..">: "..res.."% "..t end return text end Code:
function gen_unit_res(data) local text="" local res_count=AU.rescount() for i=0,res_count-2 do local res = AU.resistance( data, i ) if res>95 then res = 95 end local t="" if res> 0 then t="<label=cpi_defense_res_D>" end if res< 0 then t="<label=cpi_defense_res_U>" end text=text.."<br> -<label=cpi_defense_res_"..(i+1)..">: "..res.."% "..t end return text end Let me know if any of this works for you - if you're still having trouble, I'll try to see if I can get it to work, although my time is really limited right now. Good luck! /C\/C\ P.S. One thing I'd like to do is to be able to allow units other than Priests to be upgraded via the DLG_CHESSPIECE.UI. I'm not sure how to do this, but I thought it would be neat to allow Beholders to be upgraded to Evil Beholders, etc. when you get the Paladin Inquisition skill. It seems like there has to be a way to get it to work with units other than just Priests, but maybe this is a limitation... |
#6
|
|||
|
|||
Thank you very much for detailed advices.
Info_chesspiece.ui opening only on main window as infobox, when right click on unit in hero army. All other cases the dlg_chesspiece.ui opening when click on unit, as dialog form. Ui files easy editable, i wrote a program which can read this files, and show me visually with names and coordinates, no problem (i adjusted some ui files and png interface-textures for better appearance). But resistances: I think, the first "gen_unit_res" function maybe a trash, only the second works. Your advices was my first idea, Tried and failed. Maybe i did something wrong; but i think, its simply dont work. My second idea: creating 6 global variables, and including to loop in "gen_unit_res" this: if i==0 then fiz=res end if i==1 then mer=res end if i==2 then mag=res end if i==3 then tuz=res end if i==4 then fag=res end if i==5 then ast=res end function gen_unit_res(data) local text="" local res_count=AU.rescount() for i=0,res_count-1 do local res = AU.resistance( data, i ) if res>95 then res = 95 end local t="" if res> 0 then t="<label=cpi_defense_res_D>" end if res< 0 then t="<label=cpi_defense_res_U>" end if i==0 then fiz=res end if i==1 then mer=res end if i==2 then mag=res end if i==3 then tuz=res end if i==4 then fag=res end if i==5 then ast=res end text=text.."<br> -<label=cpi_defense_res_"..(i+1)..">: "..res.."% "..t end if Game.LocIsArena() then if Attack.act_feature(data, "humanoid") then local count = Attack.val_restore(data,"contrstrike") if count~=nil and count~="" then text = text.."<br><br>Îňâĺňíűő ŕňŕę îńňŕëîńü: "..count end end end return text end This is work, new variables got the correct resistance values, when function execute, but problems: This function execute when hint appear (onmouseover event on gui_object_name "defense" on chesspiece dialog). So not enough to open the dialog, must move the cursor over "defense" text. I can adjust this invisible object over cursor, or fullscreen Variables got the values, but new texts not refreshed actually, only when opening next time the dialog... Events and other essential things seems absolutely unavailable. Its serious? Other: I understand what do you want, great idea. But im afraid, impossible with this way. Too limited, this few modifiable thing is chaotic. With a decent editor or api, we can make castles, buildings for races, write pathfinding algorithm for ai, etcetera. Better than homm. But with this pile of diffuse code, i say, waste of time. Great, beautiful, funny and tactical game with terrible mechanism. Maybe converting models and write a new program, easiest and time-saving modding. |
#7
|
|||
|
|||
Quote:
Not sure if you can still find the mod on these boards. If not, let me know and I'll try to upload it to this thread. Note: the mod I mentioned requires KBMaster mod. |
#8
|
|||
|
|||
Yah - I know about that mod (and I'm pretty sure I have it), it would just be nice to use the UI on the unit info card to do it, though, since it works so well. Plus, I kind of wanted to make the Inquisition skill apply to units other than just Priests / Inquisitors, but work with similar pairs (i.e. Robbers -> Marauders, Barbarians -> Berserkers, Bear -> Ancient Bears, etc.).
It must be hard-coded, though, since the developers basically used the "army shop" style to perform the upgrades (especially with CW), but it seems like it is a simple logic switch to say let this unit be upgraded to another. Oh well, thought I'd mention it... /C\/C\ Quote:
|
#9
|
|||
|
|||
Quote:
I've actually been updating my HOMM3 Babies (H3B) mod to extend the spirit upgrade UI and have been doing it by hand. I've been making some changes and I was running out of room and so decided to start fiddling with the interface - your mod that did this helped me out, although when I replied to you at first I didn't realize you were the one who created this mod. Quote:
Quote:
I know that a lot of stuff in TL is hard coded, but when they went to AP and beyond they opened stuff up. Case in point, I'm still working on my H3B mod for TL and have made a change to the Ice Thorns ability where not only do they block passage, but they also hit and damage units if they are within the fall radius (the hexes surrouding the triad of 3, i.e. if the unit wasn't there a thorn would be created in that hex). I've been able to get everything working except having the damage hint show up correctly. It seems like to get it to calculate the cells properly, you have to use Attack.multiselect(3), but when you do that, if you turn on hints, the units have to be within the multiselect triad to have damage displayed even though the calccells function selects the cells surrounding that triad. So it is silly - the highlighted hexes will be the ones where the thorns go and are around the triad, but I have to place the triad on top of units (where the thorns don't go) to get it to display the damage hint, which is not correct. I haven't given up, yet, but I know what you mean when it comes to dealing with limitations of the game engine / system. If you look at Fishes and Rage Drain, though, these abilities don't show the damage either and so I think that it is most likely a limitation of TL or it was too convoluted to implement so I might give up soon and have it not display the hint just like Fishes and Rage Drain (although if I figure out how to do it for Ice Thorns, then maybe I can try to do it for these two as well). /C\/C\ |
#10
|
|||
|
|||
Hello matt,
You're the most advanced modder for KB (except may be russian one ). I have a question for you : it's possible to transfert new addition for warrior of the north to armored princess ? I mean : new unit, new skill, new spell and new ability. Rage system of WotN is crap like his campaign. There so many change in LUA files that it's not realistic to transfert them one by one, only if we can import whole files....and what files ? LUA, .TXT, all loc_ses ok but how to integrate them into the Armored princess campaign with Amelie for Hero ? My question is ridiculous, no one know. |
|
|