Moved - Spell Csating Discussion

flatlined

Active Member
step on the way to a more natural casting bot

I have been a bit bothered by the way the bot targets around the place when casting spells. It doesn't seem very natural, not at all like a player would. I decided to take a look at the code, and I've got a change here for consideration.
I think this is step one on the road to making the bot a more natural seeming "player", altho it's a bit sneaky in the way it does it.

I created a new function in the main script, it's a re-written version of "castSpell", instead called "CastSpellOnTarget", and it uses the same code except that the target's name is passed in to the function, and the code casts using /useabilityonplayer, instead of /target person, cast, re-target old target.

This is very easy to implement, it turns out, because all calls to "castspell" really go thru "CastSpellRange". This routine has the responsibility of making sure you are in range for the cast, saving your target, calling the CastSpell, and replacing your target. So I altered this routine to call my new "castspellontarget" routine.
Now it turns out you can't /doabilityontarget against certain targets very well - in fact your target has to be a PC. So the code checks if it's a pc you want to cast on and if so does it the new way, if not it goes back to the old way.

I've been using this for a while, and it works fine. There's an echo in the code you can comment out (;) which makes the code print what it tried to do, so you can test it ok and see it works. It will print things like "Gandalf Spirit of the Womble" indicating it wanted to cast Spirit of the Womble on Gandalf.

Once you make this change you will begin to see the difference in how the bot targets. The bot will assist the MA, and get the target mob, and stay on that target for almost everything. It will still heal others, cast buffs, so on, but it won't flick around all over the place while doing it.
I post this as step one in the process because now it seems like the player is using ProfitUI to cast spells etc, but the player (bot) is still targetting via /assist not using implied target. The next job would be to make the bot target thru MA or MT depending on job to do. This would make the bot totally natural seeming. I had a look at doing this, and unfortunately it's not straightforward, there are many places in the code that the changes would need to be made before it could even be tested. I'm leaving it for now, but I might get back to it.
The other area the bot needs some attention is when rezzing, it seems to use different styles depending on who wrote the code / where it is (in main file, in class file), and so some of this is a bit in need of work / standardizing, but again it needs lots of alterations, not just one place.

Code:
function CastSpellRange(int start, int finish, int xvar1, int xvar2, int targettobuff, int notall, int refreshtimer, bool castwhilemoving)
{
	variable bool fndspell
	variable int tempvar=${start}
	variable int originaltarget


	if ${Me.IsMoving} && !${castwhilemoving}
	{
		return -1
	}

	if ${targettobuff}>0 && !${Actor[${targettobuff}](exists)}
	{
		return -1
	}

	do
	{
		if ${SpellType[${tempvar}].Length}
		{

			if ${Me.Ability[${SpellType[${tempvar}]}].IsReady}
			{
				if ${targettobuff}
				{
					fndspell:Set[FALSE]
					tempgrp:Set[1]
					do
					{
						if ${Me.Maintained[${tempgrp}].Name.Equal[${SpellType[${tempvar}]}]} && ${Me.Maintained[${tempgrp}].Target.ID}==${targettobuff} && (${Me.Maintained[${tempgrp}].Duration}>${refreshtimer} || ${Me.Maintained[${tempgrp}].Duration}==-1)
						{
							fndspell:Set[TRUE]
							break
						}
					}
					while ${tempgrp:Inc}<=${Me.CountMaintained}

					if !${fndspell}
					{
						if !${Actor[${targettobuff}](exists)} || ${Actor[${targettobuff}].Distance}>35
						{
							return -1
						}

						if ${xvar1} || ${xvar2}
						{
							call CheckPosition ${xvar1} ${xvar2}
						}

						if ${Target(exists)}
						{
							originaltarget:Set[${Target.ID}]
						}

						if ${targettobuff(exists)}
						{
							if (${Actor[ID,${targettobuff}].Type.Equal[PC]})
							{
								call CastSpellOnTarget "${SpellType[${tempvar}]}" ${tempvar} ${castwhilemoving} ${targettobuff}
							}
							else
							{
								if !(${targettobuff}==${Target.ID}) && !(${targettobuff}==${Target.Target.ID} && ${Target.Type.Equal[NPC]})
								{
									target ${targettobuff}
									wait 10 ${Target.ID}==${targettobuff}
									call CastSpell "${SpellType[${tempvar}]}" ${tempvar} ${castwhilemoving}
								}
								if ${Actor[${originaltarget}](exists)}
								{
									target ${originaltarget}
									wait 10 ${Target.ID}==${originaltarget}
								}
							}

						}


						if ${notall}==1
						{
							return -1
						}
					}
				}
				else
				{
					if !${Me.Maintained[${SpellType[${tempvar}]}](exists)} || (${Me.Maintained[${SpellType[${tempvar}]}].Duration}<${refreshtimer} && ${Me.Maintained[${SpellType[${tempvar}]}].Duration}!=-1)
					{
						if ${xvar1} || ${xvar2}
						{
							call CheckPosition ${xvar1} ${xvar2}
						}

						call CastSpell "${SpellType[${tempvar}]}" ${tempvar} ${castwhilemoving}

						if ${notall}==1
						{
							return ${Me.Ability[${SpellType[${tempvar}]}].TimeUntilReady}
						}
					}
				}
			}
		}

		if !${finish}
		{
			return ${Me.Ability[${SpellType[${tempvar}]}].TimeUntilReady}
		}
	}
	while ${tempvar:Inc}<=${finish}

	return ${Me.Ability[${SpellType[${tempvar}]}].TimeUntilReady}
}

function CastSpellOnTarget(string spell, int spellid, bool castwhilemoving, int targettobuff)
{

	if ${Me.IsMoving} && !${castwhilemoving}
	{
		return
	}

	CurrentAction:Set[Casting ${spell}]

	echo ${Actor[ID,${targettobuff}].Name} ${Me.Ability[${spell}].Name}
	EQ2Execute /useabilityonplayer ${Actor[ID,${targettobuff}].Name} ${Me.Ability[${spell}].Name}

	if !${castwhilemoving}
	{
		;if spells are being interupted do to movement
		;increase the wait below slightly. Default=2
		wait 5
	}

	do
	{
		waitframe
	}
	while ${Me.CastingSpell}

	return SUCCESS
}
 

Pygar

EQ2Bot Specialist
Natural is a fairly relative term.

To me, excessive use of useabilityontarget is more un-natural than anything else.

I understand prophet does this for you for cure spells, but not for everything else, and its not realistic that someone is going to have every heal macro'd for every possible target.

Regardless, I've still considered making the change for better performance, not for apearing more natural, cause if anything it will appear less natural.
 

flatlined

Active Member
natural, mmm!

profit does this for all your heals, not just cures :)

If the targetting is changed so you target the MA (or MT), this will then look very natural. No one would know at all then :)
Right now it's a bit strange looking because you target the mob, I agree.
 
Top Bottom