forums | blogs | polls | tutorials | downloads | rules | help

Spell Rebalance: And questions about coding.

Ok, things are progressing much more smoothly now. I added some monsters spells into the mix with a balanced mix to em(mainly uber spells for nature since there are hardly no level 90-100 attack spells for em). Status spells are messed with, but I haven't tested them in a normal playthrough to see if they flow good. I dealt with all obvious gamebreakers(invincibility is acting up though, it is supposed to always be 10 seconds, but it's 46 seconds at level 150 for some reason).

Still having trouble with a melee/ranged healing spell. First it healed 0, then the game crashed when I viewed it, now I don't even see it appear in shops. Healing Hands doesn't like to be tinkered with it seems.

After that it's just testing the damage spells for imbalances and im done.

#magic refers to the level of the magical class required to use this spell (so it's either nature or combat magic), there may be a numerical limit though.
Logic.dsres contains a file called components.gas, there you should find the full description.

I guess also in DS1 you can use these variables in all formulas of a spell template. If you would set the e.g. mana costs equal #melee or #src_melee you will see it soon. For test purpose you also can use #magic as bonus for a more transparent stat (like DEX) just to check if the correct/expected value is accounted, later you may use it in any other formulas.

With item enchantments in DS1 i'm not familiar anymore.

Is there a way to put a level cap on this? I got a spell that's only affected by melee skill(works fine), but the max level doesn't seem to work with it unless it's #magic.

Assumed your old row/formula is: value = 1.5 * #melee;

Now try to expand it with:   ( condition ) ? ( ifTrue ) : ( ifFalse )

Example 1:
  value = ( ( #melee < 50 ) ? ( 1.5 * #melee ) : ( 1.5 * 50 ) );
The bonus value will be capped above melee level 50 and not grow anymore.

Example 2:
  value = 1.5 * ( ( #melee < #spell_max_level ) ? #melee : #spell_max_level );
If you set max_level = 50; in the spell template, this should perform like example 1.

Eventually you have to put the formula between double-brackets: value = [[ ... ]];
...and there may be differences between the original and the LoA version.

effect_duration = ((#ranged<#spell_max_level)?#ranged:#spell_max_level)*.85+33);

Example two doesn't seem to do anything. Ah well, son of a ...... I got it typed wrong>_>

I tried different ways, and example 2 doesn't seem to work. I tried example 1 and the game crashed when I tried to view one of the spells.

Also, I want to give the clone spell a twist. I want it to get a boost from ranged and melee levels also, but I want it a little less than what combat magic level offers. How would that be typed out if possible?

Ghoulz wrote:
effect_duration = ((#ranged<#spell_max_level)?#ranged:#spell_max_level)*.85+33);
...

There are 2+3 brackets in this term... Wink

 

Ghoulz wrote:

...
I tried different ways, and example 2 doesn't seem to work. I tried example 1 and the game crashed when I tried to view one of the spells.
...

About example 2, eventually multipling a conditional term is no good idea...
So even worse to hear that about example 1. But compare it once with the existing spell formulas, conditions within formulas should be well possible. You also will see there where [[ ]] are additionally needed.
Also check out component.gas about the differences between #melee (target related) and #src_melee (caster related), it may become critical if a formula depends on a target that isn't available yet.

 
Edit: I've just made a little test. In DSLoA, i've tried the following successfully with #melee and #dex :

[t:template,n:spell_magic_armor_test]
{
	category_name = "magic";
	doc = "spell magic armor";
	specializes = base_spell_good;
	[aspect]
	{
		gold_value = 20;
	}
	[common]
	{
		description = "Surrounds the Target with a shell of magical energy, adding  to Armor.";
		screen_name = "Magic Armor Test";
		[template_triggers]
		{
			[*]
			{
				action* = call_sfx_script( "nature_spell_sparkle" );
				condition* = receive_world_message("we_dropped");
			}
		}
	}
	[gui]
	{
		active_icon = b_gui_ig_i_ic_sp_004;
		inventory_icon = b_gui_ig_i_ic_sp_004_inv;
	}
	[magic]
	{
		//for the transformed monster/buff spell bug
		updates_on_transformed = false;

		apply_enchantments = false;
		cast_experience = (#magic*.15)+1;
		cast_range = 9;
		cast_reload_delay = 1;
		effect_duration = ( ( #magic < #spell_max_level ) ? ( 12 * #magic ) : ( 12 * #spell_max_level ) );
		is_one_shot = true;
		mana_cost = 0;
		mana_cost_modifier = ( ( #melee < ( 2 * #spell_max_level ) ) ? ( 4 * #melee + 14 ) : ( 4 * ( 2 * #spell_max_level ) + 14 ) );
	//	mana_cost_modifier = ( ( #dex < ( 2 * #spell_max_level ) ) ? ( 4 * #dex - 20 ) : ( 4 * ( 2 * #spell_max_level ) - 20 ) );
		max_level = 10;
		required_level = 1;
		requires_line_of_sight = true;
		speed_bias = 1;
		target_type_flags = tt_human_party_member | tt_and | tt_conscious_friend;
		target_type_flags_not = tt_actor_pack_only | tt_summoned;
		usage_context_flags = uc_defensive;
		state_name = armor_test;
		require_state_check = false;
		updates_on_transformed = false;	// we don't want this spell to play its effects on transformed creatures

		[enchantments]
		{
			[*]
			{
				alteration = alter_armor;
				description = "Magic Armor Test";
				duration = ( ( #magic < #spell_max_level ) ? ( 12 * #magic ) : ( 12 * #spell_max_level ) );
				value = ( ( #melee < ( 2 * #spell_max_level ) ) ? ( 4 * #melee + 4 ) : ( 4 * ( 2 * #spell_max_level ) + 4 ) );
		//		value = ( ( #dex < ( 2 * #spell_max_level ) ) ? ( 4 * #dex - 30 ) : ( 4 * ( 2 * #spell_max_level ) - 30 ) );
				is_single_instance = false;
			}
		}
	}
	[spell_status_effect]
	{
		description = "Test Armored";
		effect_script = magic_armor;
	}
}

Templarian Arch Sorcerer's picture

Oh.. It's been so long since I've done this sort of thing. It's all coming back to me from years ago, just looking at that code again. Smile

Ooohh, you can have more than 1 of the same modifier eh? No harm in having 3 mana cost modifiers and 3 values?

I was looking around a bit and was wondering. I found this on the spell haste.
attackModifier = 0.8; // ( 1 / 0.8 = 1.25 )
Is this a damage boost or nerf? I was thinking about creating a new melee spell that boosts your attack speed greatly, and drops your damage. Possibly even DEX.

Ghoulz wrote:
Ooohh, you can have more than 1 of the same modifier eh? No harm in having 3 mana cost modifiers and 3 values?

I was looking around a bit and was wondering. I found this on the spell haste.
attackModifier = 0.8; // ( 1 / 0.8 = 1.25 )
Is this a damage boost or nerf? I was thinking about creating a new melee spell that boosts your attack speed greatly, and drops your damage. Possibly even DEX.


mana_cost_modifier should only exist once (if you look at the posted code, the second mana_cost_modifier is behind // so it will be ignored).
However updates_on_transformed is listed twice (this redundancy already existed in the original file but i didn't see it yesterday) which may cause problems as soon as different values are assigned.

About the 'Haste' buff, attackModifier is a property of [spell_speed_affector] which is skrit file and no regular component (since not listed in component.gas).
So attackModifier won't affect (directly) the damage output, it only will reduce the attack duration of everybody who gets the 'Haste' buff (to fight faster, while walkModifier only treats/increases the moving speed). The comment behind the // just points on the (in)transparent fact that the current attack interval has to be multiplied with 0.8 to match the description of being 25% faster (you will do 5 hits instead of 4).
Now if you also wish to do more damage while the buff is active, you had to add alterations to do so for melee/ranged/magic. I'm not really familiar with this in DS1 but i guess there are!?

Doing more damage while attacking twice as fast would be a tad bit broken. Is it possible to add negative modifiers that decrease something instead?

Also about Clone. Would all the #SRC_STUFF pretty much flow just fine whether your melee or ranged using the spell? I think the only thing I need to alter is the mana cost.
Though maybe doing something like ((#SRC_MELEE_DAMAGE_MAX)/2); to avoid total abuse of it? Is that even right cause I don't know squat about using ().

Ghoulz wrote:
Doing more damage while attacking twice as fast would be a tad bit broken. Is it possible to add negative modifiers that decrease something instead?
...

I don't think there was any restriction in spell_speed_affector.skrit, so...
attackModifier = 1.25;
walkModifier = 0.8;
...should make the actor 25% slower (fighting and walking).

 

Ghoulz wrote:
...
Also about Clone. Would all the #SRC_STUFF pretty much flow just fine whether your melee or ranged using the spell? I think the only thing I need to alter is the mana cost.
Though maybe doing something like ((#SRC_MELEE_DAMAGE_MAX)/2); to avoid total abuse of it? Is that even right cause I don't know squat about using ().

Well I can't help you much here, you have to try out. I rarely changed spells in/for DS1, and making conclusions based on DS2 would be bad (and even there many things are not really transparent).
However i'm not really sure what #SRC_MELEE_DAMAGE_MAX exactly refers to (specially if used for an actor), it can mean on his base damage without weapon, or inclusive weapon but without bonuses...

Is there a target_type_flags for an unconscious friend? Be cool for a ranged/melee healing spell so they would only auto-cast when someone is out cold(assuming your using LoA Revived).

Oh, another thing, for now. The spell storm can only be casted once while active. What is causing that cause I want to apply that non-stacking to some other stuff if possible.

Sorry for double post. I wanted to try a couple spells that use ammo as deathrain type spells, but they just won't work that way.

I tried swamp slinger goo and it stays stuck in the air where it appeared. Would I be able to make a new version of the attack in the form of a normal spell so that it would function normally?

Where do I alter how spells behave? I also wanted to make the shadowjumper's chain tornado behave like acid gas or incinerate.

Ghoulz wrote:
....Where do I alter how spells behave? I also wanted to make the shadowjumper's chain tornado behave like acid gas or incinerate.

Spell behaviour is affected by their associated world/global/effect.gas for DS1.
[t:template,n:spell_sj_chain_tornado]
{
	category_name = "magic";
	doc = "spell gom ground lightning";
	specializes = base_spell_monster;
	[attack]
	{
		damage_max = 130;
		damage_min = 100;
	}
	[magic]
	{
		cast_range = 12;
		cast_reload_delay = 0;
		mana_cost = 0;
		requires_line_of_sight = true;
		speed_bias = 1;
		target_type_flags = tt_conscious_enemy | tt_unconscious_enemy;
		usage_context_flags = uc_offensive;
		cast_sub_animation = 1;
	}
	[spell_chain_attack]
	{
		jumps			= 3;
		radius 			= 15;
		attack_script	= dsx_sj_tornado_small;
		effect_script	= dsx_sj_tornado_chain_caster;
		dur				= 4.7;
		falloff			= 2;
	}
}

and the first effect code:
[effect_script*]
{
	name	=dsx_sj_tornado_small;

	script	=[[
		sound play s_e_spell_sj_tornado_sm at #TARGET_POSITION dist 20 30;

			set $dur 4.7;
			set $color .3,.3,0;

			// Add some randomness to the tornado.
			// First, get a simple number between zero and one.
			frandrange 0 1;
			
			// 50/50 split.  Half the time we get another random range between
			// 1 and 2, and the other half it's between -1 and -2.  This number is
			// the rotational speed of orb$, which is the foundation of the tornado.
			if(#POP < .5) { frandrange 1 3; }
			else { frandrange -1 -3; }

			// Get a random starting position for the foundation orb.
			frandrange 0 6.27;

			// Get a random radius for the foundation orb.
			frandrange .25 .5;

			// Now make the foundation orb.
			sfx create orbiter #TARGET
				"dur($dur)tin(0)tout(0)offset(0,-1,0)radius(#POP)invisible()
				phi(#POP)iphi(#POP)";
			set $orbFoundation #PEEK;
			sfx start #PEEK;

			// Add some randomness to the tornado.
			// First, get a simple number between zero and one.
			frandrange 0 1;
			
			// 50/50 split.  Half the time we get another random range between
			// 1 and 2, and the other half it's between -1 and -2.  This number is
			// the rotational speed of orb$, which is the foundation of the tornado.
			if(#POP < .5) { frandrange 3 6; }
			else { frandrange -3 -6; }

			// Get a random starting position for the foundation orb.
			frandrange 0 6.27;

			// Get a random radius for the foundation orb.
			frandrange .25 .5;

			// Now make the foundation orb.
			sfx create orbiter #TARGET
				"tin(0)tout(0)offset(0,-1,0)radius(#POP)invisible()
				phi(#POP)iphi(#POP)";
			sfx attach_point #PEEK @weapon_bone target;
			set $orb #PEEK;
			sfx start #PEEK;
			
			frandrange 0 6.27;
			frandrange -8 -10;
			frandrange .02 .03;			
			sfx create orbiter #TARGET
				"radius(.01)invisible()iphi(#POP)phi(#POP)";
			sfx rat #PEEK target;
			sfx target #PEEK $orb;
			set $orb2 #PEEK;
			sfx start #POP;

			frandrange 0 6.27;
			frandrange -9 -11;
			frandrange .03 .04;			
			sfx create orbiter #TARGET
				"radius(.02)invisible()iphi(#POP)phi(#POP)";
			sfx rat #PEEK target;
			sfx target #PEEK $orb2;
			set $orb3 #PEEK;
			sfx start #POP;

			frandrange 0 6.27;
			frandrange -10 -12;			
			frandrange .04 .05;
			sfx create orbiter #TARGET
				"radius(#POP)invisible()iphi(#POP)phi(#POP)";
			sfx rat #PEEK target;
			sfx target #PEEK $orb3;
			set $orb4 #PEEK;
			sfx start #POP;

			frandrange 0 6.27;
			frandrange -11 -13;
			frandrange .05 .06;			
			sfx create orbiter #TARGET
				"radius(#POP)invisible()iphi(#POP)phi(#POP)";
			sfx rat #PEEK target;
			sfx target #PEEK $orb4;
			set $orb5 #PEEK;
			sfx start #POP;

			frandrange 0 6.27;
			frandrange -12 -14;
			frandrange .06 .07;			
			sfx create orbiter #TARGET
				"radius(#POP)invisible()iphi(#POP)phi(#POP)";
			sfx rat #PEEK target;
			sfx target #PEEK $orb5;
			set $orb6 #PEEK;
			sfx start #POP;

			frandrange 0 6.27;
			frandrange -13 -15;
			frandrange .07 .08;
			sfx create orbiter #TARGET
				"radius(#POP)invisible()iphi(#POP)phi(#POP)";
			sfx rat #PEEK target;
			sfx target #PEEK $orb6;
			set $orb7 #PEEK;
			sfx start #POP;

			sfx create cylinder #TARGET
				"rp0(.5,.5,0)rp1(1,1,0)hp0(3,2.6,-6)hp1(3,3,0)dur($dur)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(6)";
			sfx rat #PEEK;
			sfx target #PEEK $orb;
			sfx start #POP;

			pause .05;

			sfx create cylinder #TARGET
				"rp0(.37,.37,0)rp1(.5,.5,0)hp0(2.7,2.3,-6)hp1(2.7,2.7,0)dur(4.6)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(8)";
			sfx rat #PEEK;
			sfx target #PEEK $orb2;
			sfx start #POP;

			pause .05;

			sfx create cylinder #TARGET
				"rp0(.255,.255,0)rp1(.32,.32,0)hp0(2.4,2,-6)hp1(2.4,2.4,0)dur(4.5)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(10)";
			sfx rat #PEEK;
			sfx target #PEEK $orb3;
			sfx start #POP;

			pause .05;

			sfx create cylinder #TARGET
				"rp0(.2,.2,0)rp1(.245,.245,0)hp0(2.1,1.7,-6)hp1(2.1,2.1,0)dur(4.4)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(12)";
			sfx rat #PEEK;
			sfx target #PEEK $orb4;
			sfx start #POP;

			pause .05;
			
			sfx create cylinder #TARGET
				"rp0(.145,.145,0)rp1(.19,.19,0)hp0(1.8,1.1,-6)hp1(1.8,1.8,0)dur(4.3)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(14)";
			sfx rat #PEEK;
			sfx target #PEEK $orb5;
			sfx start #POP;

			pause .1;
			
			sfx create cylinder #TARGET
				"rp0(.11,.11,0)rp1(.135,.135,0)hp0(1.2,.5,-6)hp1(1.2,1.2,0)dur(4.1)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(16)";
			sfx rat #PEEK;
			sfx target #PEEK $orb6;
			sfx start #POP;

			pause .1;

			sfx create cylinder #TARGET
				"rp0(.075,.075,0)rp1(.1,.1,0)hp0(.6,0,-6)hp1(.6,.6,0)dur(3.9)
				tin(0)tout(0)color0($color)texture(b_sfx_cyl_tornado)dark()
				spin(18)";
			sfx rat #PEEK;
			sfx target #PEEK $orb7;
			sfx start #POP;

			pause .05;

			sfx create fire #TARGET
				"dark()color0(.1,.1,.07)color1(0,0,0)dur(3.8)velocity(0,0,0)accel(0,0,0)";
			sfx rat #PEEK;
			sfx target #PEEK $orb;
			sfx start #POP;

			sfx create orbiter #TARGET
				"radius(1.8)offset(0,2.7,0)dur(3.8)tin(0)tout(0)iphi(-2)scale(.4)
				color0(.6,.6,1)";
			sfx rat #PEEK;
			sfx target #PEEK $orb;
			set $orbLightning #PEEK;
			sfx start #POP;

			sfx create lightning #TARGET_KB 
				"must_update()offset(0,.2,0)bolt_life(1)mindisplace(-.1)
				maxdisplace(.1)color0(.6,.6,1)[0]subd(.6)scale(.5)";
			sfx target #PEEK $orbLightning;
			sfx start #POP;

			worldmsg WE_SPELL_SYNC_END #INVALID_GOID #OWNER_GOID #TARGET_GOID;
			]];
}

Is used to in conjunction with "dsx_sj_tornado_chain_caster" to determine the colors and where the effect starts and how it travels.

Went through a lot of trial and error when I made my Laser Beam spell almost 3 years ago. (WOW, Didn't realize it was that long ago.)

Hope this helps somewhat. Smile

The spell won't function without both effects will it? So can I keep the chain attack script without actually having the attack chain to another target? I tried this and that and the spell doesn't even cause damage. Im trying to get the spell to hurt something, and work with damage per second.

What's the difference between #TARGET and #TARGET_KB? Acid Gas and Incinerate have that instead.

I don't think you can change the spell attack parameters. Been a while, but I think I remember running into that same problem with Laser Beam (not doing damage etc.). So "spell_chain_attack" has to be used for that effect. As for the difference between #TARGET and #TARGET_KB, I'm not 100% certain but I believe #TARGET_KB is referencing the 3d mesh bone_translator. Calling the effect at the target's "kill_bone"

When I added the chain tornado the first time I only altered the duration, and added the usual stuff you find in a spell script, and the spell didn't do damage. Iunno, that spell is very sensitive to changes. The effect duration might always have to be 4.7 or something.

I forgot to ask, but with guns and spell effects, do you just create an ammo template of the spell, or do you need to alter the attachpoints of the spell effect also? Well, obviously with monster spells like the robo suit torso attack, but normal spells that come out of your hand?

The wpn_projectile.gas covers the basics for ammo templates. Some reference effects, others do not. I usually just experiment with different things till I give up or they finally work. ^^

Im looking at the templates for Fury Gas and Inferno. I been trying to get the fury gas to jet out of the caster's hand and towards the target(not into the air or backwards or w/e).

Inferno

sound play s_e_spell_flame_cast at #SOURCE_POSITION dist 10 30;
sound play s_e_spell_burnbody_cast at #SOURCE_POSITION dist 10 30;

sfx create fireb #SOURCE
"offset(0,.2,.5)must_update()color0(0,0,0)fctrl(0,0,0)
velocity(0,0,40)accel(0,0,0)cvel(1)alphafade(1)end_rate(1000)
lower_r0(12)lower_r1(12)upper_r0(12)upper_r1(12)count(30)
flamesize(2)[0][1]max_displace(15)min_displace(-15)";
sfx start #POP;

Fury Gas

set $flames1 100;
set $flames2 100;

set $width1 20;
set $width2 40;

sound play s_e_spell_fury_gas_cast at #TARGET_POSITION dist 3 20;

sfx create fireb #SOURCE
"must_update()dark()fctrl(0,1,10)flamesize(4)alphafade(.5)dur(.7)
color0(.4,1,0)velocity(0,-60,60)accel($accel)cvel(1)lower_r0(0)
lower_r1(0)upper_r0($width1)upper_r1($width2)count($flames2)
bone_orient()[0]";
sfx attach_point #PEEK @weapon_bone target;
sfx friendly party #PEEK;
sfx start #POP;

Anything in there that tells the direction for it to go?

[effect_script*]
{
	name	=fury_gas;

	script	=[[
            
            set $accel 0,30,-20;

			set $flames1 100;
			set $flames2 100;

			set $width1 20;
			set $width2 40;

			sound play s_e_spell_fury_gas_cast at #TARGET_POSITION dist 3 20;
			
			sfx create fireb #SOURCE 
				"must_update()dark()fctrl(0,1,10)flamesize(4)alphafade(.5)dur(.7)
				color0(.4,1,0)velocity(0,-60,60)accel($accel)cvel(1)lower_r0(0)
				lower_r1(0)upper_r0($width1)upper_r1($width2)count($flames2)
				bone_orient()[0]";
			sfx attach_point #PEEK Bone_Jaw target;
			sfx friendly party #PEEK;
			sfx start #POP;

			sfx create fireb #SOURCE 
				"must_update()fctrl(0,0,1)flamesize(.3)alphafade(.5)dur(.7)
				color0(1,1,0)velocity(0,-60,60)accel($accel)cvel(1)lower_r0(0)
				lower_r1(0)upper_r0($width1)upper_r1($width2)count($flames2)
				bone_orient()";
			sfx attach_point #PEEK Bone_Jaw target;
			sfx friendly party #PEEK;
			sfx start #POP;

			sfx create fireb #SOURCE 
				"must_update()fctrl(0,1,10)flamesize(1)alphafade(.5)dur(.7)
				color0(.6,.8,0)velocity(0,-60,60)accel($accel)cvel(1)
				lower_r0(3)lower_r1(5)upper_r0($width1)upper_r1(60)
				count($flames2)bone_orient()";
			sfx attach_point #PEEK Bone_Jaw target;
			sfx friendly party #PEEK;
			sfx start #POP;

			worldmsg WE_SPELL_SYNC_END #INVALID_GOID #OWNER_GOID #TARGET_GOID;

           	]];
}

Hmmm, the effect keeps going down into the ground, but the damage is going straight now...

Aha, velocity is what determines the effect's direction. That -60 is what must be causing it to go downward. Setting the middle to 0 levels it out. Nice, now I can get back to business.

I wonder, does lower_r0(0)lower_r1(0)upper_r0($width1)upper_r1($width2) determine the shape of the effect? I basically copied from that and the effect's shape looks like the one I copied from.

Jesus, I don't even wana know how those Zero gun effect were cooked up. I don't understand any of that kind of crap. Gun effects are too complex. Templates look nothing like the spell effect they're based on.