View unanswered posts | View active topics
|
Page 1 of 1
|
[ 13 posts ] |
|
| Author |
Message |
|
Bracco
|
Post subject: Mobile.swing() Posted: Sun Jan 14, 2007 12:02 pm |
|
Joined: Thu Dec 28, 2006 3:52 pm Posts: 80
|
title is not so clear  but i mean a method for mobiles that causes an attack with the weapon (not the animation only)(without waiting the delay and/or movement check for projectables), just like when you are in warmode and swing with your weapon...
useful to implement things such as the aos combat abilities (double strike, moving shot etc)
Last edited by Bracco on Sun Jan 14, 2007 12:30 pm, edited 1 time in total.
|
|
| Top |
|
 |
|
SMJ
|
Post subject: Posted: Sun Jan 14, 2007 12:25 pm |
|
Joined: Wed May 10, 2006 9:15 pm Posts: 113
|
Code: use uo;
function PlayAttackAnimation(byref a_info) var attack_anim := ANIM_FIDGET_1; // Default attack anim for NPCs. if ( (a_info.cfginfo).Anim ) // Normal weapons var anim_list := GetConfigStringArray(a_info.cfginfo, "Anim"); attack_anim := anim_list[RandomInt(anim_list.Size())+1]; elseif ( (a_info.cfginfo).AttackAnimation ) // NPC intrinsic weapons var anim_list := GetConfigStringArray(a_info.cfginfo, "AttackAnimation"); attack_anim := anim_list[RandomInt(anim_list.Size())+1]; endif
PerformAction(a_info.mobile, CInt(attack_anim));
return attack_anim; endfunction
Copy-pasted from 096 combatHook.src
|
|
| Top |
|
 |
|
Bracco
|
Post subject: Posted: Sun Jan 14, 2007 12:29 pm |
|
Joined: Thu Dec 28, 2006 3:52 pm Posts: 80
|
SMJ wrote: Code: use uo;
function PlayAttackAnimation(byref a_info) var attack_anim := ANIM_FIDGET_1; // Default attack anim for NPCs. if ( (a_info.cfginfo).Anim ) // Normal weapons var anim_list := GetConfigStringArray(a_info.cfginfo, "Anim"); attack_anim := anim_list[RandomInt(anim_list.Size())+1]; elseif ( (a_info.cfginfo).AttackAnimation ) // NPC intrinsic weapons var anim_list := GetConfigStringArray(a_info.cfginfo, "AttackAnimation"); attack_anim := anim_list[RandomInt(anim_list.Size())+1]; endif
PerformAction(a_info.mobile, CInt(attack_anim));
return attack_anim; endfunction Copy-pasted from 096 combatHook.src
hm? i mean a REAL swing, not just the animation...
|
|
| Top |
|
 |
|
SMJ
|
Post subject: Posted: Sun Jan 14, 2007 12:35 pm |
|
Joined: Wed May 10, 2006 9:15 pm Posts: 113
|
Then add the damage, too? I'm sorry, but this already exists in the form of:
Code: Attack( byref attacker, byref defender );
And the suggestion would limit, rather than expand, POL's combat aesthetics. Every weapon has 9 attack animations, but the coders decide which ones to utilize; by adding them to a custom exported Attack(byref attacker, byref defender) function.
|
|
| Top |
|
 |
|
Bracco
|
Post subject: Posted: Sun Jan 14, 2007 12:47 pm |
|
Joined: Thu Dec 28, 2006 3:52 pm Posts: 80
|
SMJ wrote: Then add the damage, too? I'm sorry, but this already exists in the form of: Code: Attack( byref attacker, byref defender ); And the suggestion would limit, rather than expand, POL's combat aesthetics. Every weapon has 9 attack animations, but the coders decide which ones to utilize; by adding them to a custom exported Attack(byref attacker, byref defender) function.
i dont get it  where's that attack function from? from a script?
i need to cause a physical attack, just as when i am hitting someone with my executioner's axe... it can't be done with attackhook/hitscript, i need to be able to actually cause the attack to happen, not wait till the normal one happens
|
|
| Top |
|
 |
|
SMJ
|
Post subject: Posted: Sun Jan 14, 2007 12:58 pm |
|
Joined: Wed May 10, 2006 9:15 pm Posts: 113
|
That's called "externalizing" and can be very easily done with an include function. All it really means is that you take out all of the contents of a program, stick it in a function, then make a call to it in the function, so that several different scripts can perform identical purposes without copy-pasting too much content.
Code: program DoStuff(who) return DoStuffFunc(who); endprogram
Code: function DoStuffFunc(who) // Do all the program's functions endfunction
|
|
| Top |
|
 |
|
Bracco
|
Post subject: Posted: Sun Jan 14, 2007 1:08 pm |
|
Joined: Thu Dec 28, 2006 3:52 pm Posts: 80
|
SMJ wrote: That's called "externalizing" and can be very easily done with an include function. All it really means is that you take out all of the contents of a program, stick it in a function, then make a call to it in the function, so that several different scripts can perform identical purposes without copy-pasting too much content. Code: program DoStuff(who) return DoStuffFunc(who); endprogram
Code: function DoStuffFunc(who) // Do all the program's functions endfunction
hm... i think you totally misunderstood what i'm saying.
i DON'T want to hook the attack, i want to MAKE IT HAPPEN.
also, i know what hooks, exported functions and such things are.
let me explain in a more ground-to-ground way:
i want to implement, for example, AOS combat ability "Double Strike"
what it does is, basically, to attack 2 times in a row, so when your attack lands another one is instantly fired.
how do you do this nowadays? you can't, unless you do it some tricky way, making a fake attack in an hitscript, but maybe, as you say, you have some attackhook/hitscript you want to run before the new attack lands (if it lands)
not to mention that the movement-check for projectable weapons is done by core, so you won't have anything to hook to implement "Moving Shot" (ofc you can make a "fake attack", but it will result in an heavy script to make it work just as the core does)
|
|
| Top |
|
 |
|
SMJ
|
Post subject: Posted: Sun Jan 14, 2007 1:25 pm |
|
Joined: Wed May 10, 2006 9:15 pm Posts: 113
|
|
I know exactly what you're saying. You want it to fire twice? Externalize it to a function, and fire it twice. You want it to wait until you would swing normally? Make the command put a cprop on the attacker, and then loop it in the syshook; that way it'll skip the attack delay entirely. I haven't tried using projectiles in a syshook myself, but I don't see why "moving shot" couldn't be done. I don't know exactly how AOS "Moving Shot" works, but if it just means that you use it to shoot while moving; just link a script to it. And if you're worried about a syshook stalling the server, just make the packethook immediately Start_Script another file; and you've solved the problem.
As far as a "heavy script", I don't see where you got that conclusion. 096 AND 097 have a syshook, WOD used a syshook, SxC uses a syshook, I use a syshook, and I have never heard of anyone complaining about ANY of them being slow or heavy.
There is no limit to what you can and cannot do; just a limit to creativity, and what you're willing to try.
|
|
| Top |
|
 |
|
Bracco
|
Post subject: Posted: Sun Jan 14, 2007 1:39 pm |
|
Joined: Thu Dec 28, 2006 3:52 pm Posts: 80
|
SMJ wrote: I don't know exactly how AOS "Moving Shot" works, but if it just means that you use it to shoot while moving; just link a script to it.
meh, lets suppose that i use a script to make a "fake" attack while moving.
i put a start_script in my packethook that fires the "fake attack" script
so i must do something like this
Code: if( attackhook ) call hook if hook returned 1, exit endif
if( weapon is projectile ) try to comsume projectile if none, exit exit
if( weapon is projected ) play sound and animations else play attack anim endif
if( combat advancement hook exists ) call it endif
hit_chance = (weapon_attribute + 50.0) / (2.0 * opponent_weapon_attribute + 50.0)
if( random_float(1.0) < hitchance ) play hit sounds and anims damage weapon (1 in 100 chance to lose 1 hp) damage = random_weapon_die_damage damage_multiplier = tactics + 50 damage_multiplier += strength * 0.2 damage_multiplier *= 0.01 damage *= damage_multiplier if( opponent has shield ) call parry advancement hook parry_chance = opponent_parry_skill / 200.0 if( random_float(1.0) < parry_chance ) display parry success damage -= opponent_shield_ar endif endif if( weapon has no hit script ) choose armor piece hit based on zone coverage percentage blocked = armor piece ar + character ar_mod absorbed = blocked / 2 blocked -= absorbed absorbed += random_int(blocked+1) damage -= absorbed if( damage >= 2.0 ) damage *= 0.5 endif 1 in 100 chance for armor piece to lose 1 hp play hit animation applydamage(damage) else choose armor piece hit based on zone coverage percentage calc base & raw damage (exactly like above if no hit script) run hit script (Core doesn't damage armor if hitscript, do it in the script) endif else play weapon miss sound endif
that's the core combat pseudocode...
sooo its good to make such a thing in a script that probably will run continuosly during pvp battles?
no its not. moreover, there's really no reason to just make a script clone of an internal core function.
and tbh i dont like filling the scriptbase with intricated, tricky things just to fake out something that it's already been done internally
|
|
| Top |
|
 |
|
SMJ
|
Post subject: Posted: Sun Jan 14, 2007 1:45 pm |
|
Joined: Wed May 10, 2006 9:15 pm Posts: 113
|
Guess what?
Code: /* $Id: combatHook.src 788 2006-09-05 01:25:54Z AustinHeilman $ * * NOTES: * Return 0 if you want the core to handle the * combat cycle. Return 1 to say that the cycle is over. */
use uo; use os; use polsys; use cfgfile;
include ":attributes:attributes"; include ":brainai:npcUtil"; include ":armor:armorZones"; include ":combat:settings"; include ":damage:damage"; include ":itemutils:itemdesc"; include "include/client"; include "include/facings";
/* * Global variables * With the way hooks work, these are only set only ONCE * and stay the same in every instance the hook gets run. */ var g_item_cfg := ReadConfigFile(":*:itemdesc"); var g_settings_cfg := CS_GetSettingsCfgFile();
program Install() print("INSTALLING: Combat hook... "); return 1; endprogram
exported function Attack(attacker, defender) if ( !g_settings_cfg["Settings"].EnableHook ) return 0; elseif ( !CanAttack(attacker, defender) ) return 1; endif
var a_info, d_info; SetupInfo(attacker, defender, a_info, d_info);
if ( !DistanceChecks(a_info, d_info) ) return 1; elseif ( !AmmoChecks(a_info, d_info) ) return 1; endif
FacingChecks(attacker, defender); PlayAttackAnimation(a_info);
var hit_chance := CalcHitDifficulty(a_info, d_info); if ( RandomFloat(1.0) < hit_chance ) var attribute := GetConfigString(a_info.cfginfo, a_info.prefix+"Attribute"); var gain_flag := GetCombatGainFlags(attacker, defender); SkillCheck(attacker, attribute, -1, 0, gain_flag);
PlayHitSound(a_info, d_info);
var base_damage := CalcBaseDamage(a_info); var raw_damage := base_damage; ParryChecks(attacker, defender, raw_damage);
var armor_hit := GetArmorHit(d_info); ArmorChecks(d_info, armor_hit, raw_damage);
RunWeaponHitScripts(a_info, d_info, armor_hit, base_damage, raw_damage); RunArmorHitScripts(a_info, d_info, armor_hit, base_damage, raw_damage);
ApplyRawDamageEX(d_info.mobile, raw_damage, DMG_FORCED, a_info.mobile); else PlayMissSound(a_info); endif
return 1; endfunction
function GetCombatGainFlags(attacker, defender) if ( defender.npctemplate ) return ADV_ALL; elseif ( attacker.npctemplate ) return ADV_ALL; elseif ( g_settings_cfg["Settings"].PvPGains ) return ADV_ALL; else return ADV_DISABLE; endif endfunction
function CanAttack(attacker, defender) // These first two checks are handled by the core. //if ( attacker == defender ) // return 0; //elseif ( !CheckLineOfSight(attacker, defender) ) // return 0; // if ( !attacker.warmode && !g_settings_cfg["Settings"].AutoDefend ) return 0; endif
return 1; endfunction
function FacingChecks(attacker, defender) if ( g_settings_cfg["Settings"].ForceFacing ) if ( !IsFacing(attacker, defender.x, defender.y) ) TurnObjectToward(attacker, defender.x, defender.y); endif
if ( !IsFacing(defender, attacker.x, attacker.y) ) TurnObjectToward(defender, attacker.x, attacker.y); endif endif
return 1; endfunction
function DistanceChecks(byref a_info, byref d_info) // Core handles distance checks before starting the hook. return 1; /* var cur_range := Distance(a_info.mobile, d_info.mobile); var max_range := GetConfigInt(a_info.cfginfo, a_info.prefix+"MaxRange"); if ( max_range == error ) max_range := 1; endif
if ( cur_range > max_range ) CombatMsg(a_info.mobile, "Opponent is too far away. ["+max_range+"]", "Dist"); return 0; elseif ( cur_range < CInt(GetConfigInt(a_info.cfginfo, a_info.prefix+"MinRange")) ) CombatMsg(a_info.mobile, "Opponent is too close.", "Dist"); return 0; else return 1; endif */ endfunction
function AmmoChecks(byref a_info, byref d_info) var ammo_type := CInt((a_info.cfginfo).ProjectileType); if ( !ammo_type ) return 1; endif
if ( ConsumeSubstance((a_info.mobile).backpack, ammo_type, 1) ) PlaySoundEffect(a_info.mobile, CInt((a_info.cfginfo).ProjectileSound)); PlayMovingEffect(a_info.mobile, d_info.mobile, (a_info.cfginfo).ProjectileAnim, 10, 0); return 1; else CombatMsg(a_info.mobile, "You do not have any "+GetObjTypeDesc(ammo_type, 1)+"!", "Ammo"); return 0; endif endfunction
function PlayAttackAnimation(byref a_info) var attack_anim := ANIM_FIDGET_1; // Default attack anim for NPCs. if ( (a_info.cfginfo).Anim ) // Normal weapons var anim_list := GetConfigStringArray(a_info.cfginfo, "Anim"); attack_anim := anim_list[RandomInt(anim_list.Size())+1]; elseif ( (a_info.cfginfo).AttackAnimation ) // NPC intrinsic weapons var anim_list := GetConfigStringArray(a_info.cfginfo, "AttackAnimation"); attack_anim := anim_list[RandomInt(anim_list.Size())+1]; endif
PerformAction(a_info.mobile, CInt(attack_anim));
return attack_anim; endfunction
function CalcHitDifficulty(byref a_info, byref d_info) //hit_chance = (weapon_attribute + 50.0) / (2.0 * opponent_weapon_attribute + 50.0) var a_skill := AP_GetSkill(a_info.mobile, GetConfigString(a_info.cfginfo, a_info.prefix+"Attribute")); var d_skill := AP_GetSkill(d_info.mobile, GetConfigString(d_info.cfginfo, d_info.prefix+"Attribute"));
return ((a_skill + 50.0) / (2.0 * d_skill + 50)); endfunction
function PlayHitSound(byref a_info, byref d_info) var hit_sound := GetConfigStringArray(a_info.cfginfo, a_info.prefix+"HitSound"); hit_sound := hit_sound[RandomInt(hit_sound.Size())+1]; PlaySoundEffect(a_info.mobile, CInt(hit_sound));
var damaged_sound; if ( (d_info.mobile).npctemplate ) damaged_sound := GetConfigStringArray(d_info.cfginfo, "DamagedSound"); else case ( (d_info.mobile).gender ) 0:// Male damaged_sound := array{341, 342, 343, 345, 346}; break; 1://Female damaged_sound := array{332, 333, 334, 335, 336}; break; endcase endif damaged_sound := damaged_sound[RandomInt(damaged_sound.Size())+1];
PlaySoundEffect(d_info.mobile, CInt(damaged_sound));
return 1; endfunction
function PlayMissSound(byref a_info) var miss_sound := GetConfigStringArray(a_info.cfginfo, a_info.prefix+"MissSound"); miss_sound := miss_sound[RandomInt(miss_sound.Size())+1]; PlaySoundEffect(a_info.mobile, CInt(miss_sound));
return 1; endfunction
function CalcBaseDamage(byref a_info) var base_dmg := GetConfigString(a_info.cfginfo, a_info.prefix+"Damage"); base_dmg := RandomDiceRoll(base_dmg);
var dmg_mult := CDbl(AP_GetSkill(a_info.mobile, TACTICS))+50.0; dmg_mult += (CDbl(AP_GetStat(a_info.mobile, STRENGTH)) * 0.2); dmg_mult := CDbl(dmg_mult) * 0.01; base_dmg *= dmg_mult;
return CInt(base_dmg); endfunction
function ParryChecks(byref a_info, byref d_info, byref raw_damage) var shield := (d_info.mobile).shield; if ( !shield ) return 0; endif
var parry_elem := g_settings_cfg["Parry"]; var divisor := CDbl(parry_elem.ParryDivisor); var roll := CDbl(parry_elem.ParryRoll); var parry_chance := CDbl(AP_GetSkill(a_info.mobile, PARRY)) / divisor;
if ( RandomFloat(roll) < parry_chance ) PerformAction(d_info.mobile, ANIM_TWIST_DODGE); SendSysMessage(d_info.mobile, "You deflect some damage using your shield."); raw_damage -= shield.ar;
var armor_elem := g_settings_cfg["Armor"]; if ( RandomInt(100)+1 <= armor_elem.WearChance ) SendSysMessage(d_info.mobile, shield.desc+" takes some damage."); shield.hp -= 1;
if ( shield.hp <= 1 ) MoveObjectToLocation(shield, 1, 1, 1, shield.realm, MOVEOBJECT_FORCELOCATION); SendSysMessage(d_info.mobile, shield.desc+" has been destroyed."); DestroyItem(shield); endif endif endif
return 1; endfunction
function GetArmorHit(byref d_info) var hit_zone := CS_GetRandomArmorZone(); var armor_hit := CS_GetEquipmentInArmorZone(d_info.mobile, hit_zone);
if ( armor_hit.Size() < 1 ) return 0; endif
var best_armor := 0; foreach item in ( armor_hit ) if ( item.ar > best_armor.ar ) best_armor := item; endif SleepMS(2); endforeach
return best_armor; endfunction
function ArmorChecks(byref d_info, armor_hit, byref raw_damage) var blocked := CInt(armor_hit.ar) + (d_info.mobile).ar_mod; var absorbed := blocked / 2; blocked := blocked - absorbed; absorbed := absorbed + RandomInt(blocked+1)+1; raw_damage := raw_damage - absorbed;
if ( raw_damage >= 2.0 ) raw_damage := raw_damage * 0.5; endif raw_damage := CInt(raw_damage);
if ( !armor_hit.IsA(POLCLASS_ARMOR) ) return 1; endif
var armor_elem := g_settings_cfg["Armor"]; if ( RandomInt(100)+1 <= armor_elem.WearChance ) SendSysMessage(d_info.mobile, armor_hit.desc+" takes some damage."); armor_hit.hp -= 1;
if ( armor_hit.hp <= 1 ) MoveObjectToLocation(armor_hit, 1, 1, 1, armor_hit.realm, MOVEOBJECT_FORCELOCATION); SendSysMessage(d_info.mobile, armor_hit.desc+" has been destroyed."); DestroyItem(armor_hit); endif endif
return 1; endfunction
function RunWeaponHitScripts(byref a_info, byref d_info, armor_hit, base_damage, raw_damage) var weapon_scripts := array{}; if ( ((a_info.mobile).weapon).intrinsic ) weapon_scripts := GetObjProperty(a_info.mobile, "HitScripts"); elseif ( ((a_info.mobile).weapon).IsA(POLCLASS_WEAPON) ) weapon_scripts := GetObjProperty((a_info.mobile).weapon, "HitScripts"); endif
var params := array{a_info.mobile, d_info.mobile, (a_info.mobile).weapon, armor_hit, base_damage, raw_damage}; foreach hitscript in ( weapon_scripts ) var script := Start_Script(hitscript, params); if ( !script || script.errortext ) SendSysMessage(a_info.mobile, "*Attacker* Weapon script error starting ["+hitscript+"] :"+script.errortext); SendSysMessage(d_info.mobile, "*Attacker* Weapon script error starting ["+hitscript+"] :"+script.errortext); endif SleepMS(2); endforeach
return 1; endfunction
function RunArmorHitScripts(byref a_info, byref d_info, armor_hit, base_damage, raw_damage) var body_scripts := GetObjProperty(d_info.mobile, "ArmorHitScripts"); var armor_scripts := GetObjProperty(armor_hit, "ArmorHitScripts"); if ( !body_scripts ) body_scripts := array{}; endif if ( !armor_scripts ) armor_scripts := array{}; endif
armor_scripts := armor_scripts + body_scripts;
var params := array{a_info.mobile, d_info.mobile, (a_info.mobile).weapon, armor_hit, base_damage, raw_damage}; foreach hitscript in ( armor_scripts ) var script := Start_Script(hitscript, params); if ( !script || script.errortext ) SendSysMessage(a_info.mobile, "*Defender* Armor script error starting ["+hitscript+"] :"+script.errortext); SendSysMessage(d_info.mobile, "*Defender* Armor script error starting ["+hitscript+"] :"+script.errortext); endif SleepMS(2); endforeach
return 1; endfunction
function SetupInfo(attacker, defender, byref a_info, byref d_info) a_info := struct; a_info.+mobile := attacker; if ( attacker.IsA(POLCLASS_NPC) && (attacker.weapon).intrinsic ) a_info.+prefix := "Attack"; a_info.+cfginfo := NPC_GetNPCConfig(attacker.npctemplate); else a_info.+prefix := ""; a_info.+cfginfo := g_item_cfg[(attacker.weapon).objtype]; endif
d_info := struct; d_info.+mobile := defender; if ( defender.IsA(POLCLASS_NPC) && (defender.weapon).intrinsic ) d_info.+prefix := "Attack"; d_info.+cfginfo := NPC_GetNPCConfig(defender.npctemplate); else d_info.+prefix := ""; d_info.+cfginfo := g_item_cfg[(defender.weapon).objtype]; endif
return 1; endfunction
function CombatMsg(mobile, text, type:="") // This is done just to prevent message spam on fast weapons. if ( CInt(GetObjProperty(mobile, "#CH-Msg"+type)) < ReadMillisecondClock() ) SendSysMessage(mobile, text); SetObjProperty(mobile, "#CH-Msg"+type, ReadMillisecondClock()+800); endif
return 1; endfunction
The distro already does it. And nobody's complained. And it really doesn't get that much overhead.
Either apply my advice, or ignore it. I'm never going to use AOS systems; I wasn't particularly impressed with them; but I have seen entire shards pull this kind of thing off, and the distro actually uses it by default. If you get complaints about this being slow, then it's your computer, not POL.
Last edited by SMJ on Sun Jan 14, 2007 1:52 pm, edited 1 time in total.
|
|
| Top |
|
 |
|
Bracco
|
Post subject: Posted: Sun Jan 14, 2007 1:50 pm |
|
Joined: Thu Dec 28, 2006 3:52 pm Posts: 80
|
|
fine, so you're telling there's no reason to have it core side no?
well, i disagree. have you ever seen how such scripts can suck up resources when there are a coulpe hundreds ppl online fighting continuously?
i have, and i didn't like the result
edit: advice what? you just came here and sentenced it itsn't necessary. also you say that its good to use crappy methods, just pump up the hardware (oh, just to point it out, hooking isnt a crappy method, faking an entire existing system is)
btw, enough with discussion. let devs decide if this is worth implementing or not
|
|
| Top |
|
 |
|
Austin
|
Post subject: Posted: Tue Jan 30, 2007 4:18 pm |
|
 |
| POL Developer |
 |
Joined: Wed Jan 25, 2006 6:30 am Posts: 383 Location: San Diego, California
|
|
The nice thing about hooked (exported) scripts is that the core caches.. sort of.. remembers the code. This is why they cant be unloaded and reloaded, too.
It just goes through and refreshes the data it is instructed to.. very optimized part of the execution engine. Only one instance of a hook can run at a time but they run so quickly and in their own threads, that they it isn't too big a deal.
_________________ -Austin
|
|
| Top |
|
 |
|
MuadDib
|
Post subject: Posted: Tue Jan 30, 2007 10:40 pm |
|
 |
| POL Developer |
 |
Joined: Mon Feb 13, 2006 1:50 am Posts: 830 Location: Indiana, USA
|
|
Actually for aos combat systems like the double strike, etc, it IS doable without hooking the core combat. To the best of my knowledge about the only thing not doable is the Lightning Strike of Bushido because it enhances your ability to hit the opponent (totally core controlled). The others are modifiers to the successful attack. Others are speed mods, which .delay can be used for this now with core combat without hooking. I have not messed with combat hooks, so don't know personally if you can set the hit percentage chance in the script or not. If so, then even lightning strike is done.
From my personal pvp/pvm on OSI, with all the basic skills, Spellweaving, Bushido, Necro, Chivalry, etc (all cept ninjitsu), including the combat book mods, it's all doable in the hitscripts and so forth without hardly any overhead required at all. Only if you must hook core combat might that make more overhead than desired I would think.
_________________ POL Developer - The Penguin Scripter
|
|
| Top |
|
 |
|
Page 1 of 1
|
[ 13 posts ] |
|
Who is online |
Users browsing this forum: No registered users and 0 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|

|