Skele mages- automatic searching for souls of a given element?

Anything and everything related to the Evolution server.
Post Reply
User avatar
Silly_Warlock
Killer in Training
Posts: 44
Joined: Tue Sep 17, 2013 8:56 am

Currently when we want to summon a skeletal mage of a given element we need to either wait for selection to stumble upon a proper soul or read through our soul list and then stop to type in alt activation command with monster name (typos FTW).

It would be an improvement if we could choose the type of spawned mage without having to stop playing (or waiting for an unknown amount of time and hoping).
One way of handling that is to make alt activate iterate through modes while making activate try finding suitable soul for the mode and spawning mage if it succeeds.

Example implementation:
7 soul selection modes:
  • First soul- pick weakest soul (first on list)
  • Random element- pick a soul with max amount of possible results, ask for confirmation if less than 5 possible elements, fail if only 1 element
  • 5 elements(resis)- pick a soul with given element, ask for confirmation if more than 1 possible element or in last quarter of the soul list (might not want to use luci for mage :p), fail on lack of given element or presence of all elements
On alt activate:
  • No argument- next mode, search for soul and show the pick to player or ask for confirmation if needed (shows the pick + possible elements, asks to activate within n seconds to spawn)
  • Element/Mode- set mode, activate
  • Monster name- same as was
On activate- pick a soul, spawn mage or ask for confirmation or fail.

Code: Select all

class ArtifactSillySummonSkeletalMage extends ArtifactSummonSkeletalMage
	Config(MonsterAssaultRPG);

var enum EMode
{
	M_Random,
	M_First,	
	M_Physical,
	M_Ice,
	M_Fire,
	M_Poison,
	M_Lightning
} Mode;

var int MaxPressDelay;
var int LastCancelledPressTime;
var bool bSpawnAnyways;
var bool bLastCancelled;


function Activate()
{
	bSpawnAnyways = false;
	if(bLastCancelled && Level.TimeSeconds - LastCancelledPressTime <= MaxPressDelay)
	    bSpawnAnyways = true;
	bLastCancelled = false;
	
	Super.Activate();
}

function AltActivate(optional string Param)
{
	local int i;
	local int iSoul;

	if (InvSoul == None || Instigator == None)
	{
		Destroy();
		return;
	}

    //Next mode
    if (Mode < EMode.EnumCount - 1)
	Mode = EMode(Mode+1);
    else
	Mode = EMode(0);
    Instigator.ClientMessage(GetEnum(Enum'EMode', Mode));

    if (Param != "")
    {
		//attempt to summon a monster with a soul matching this name
		for (i = 0; i < InvSoul.SoulClasses.length; i++)
		{
			if (strcmp(InvSoul.SoulClasses[i].Default.FriendlyName, Param) != 0)
				continue;

			//found a soul...summon this monster using this soul
			SoulIndex = i;
			Activate();
			SoulIndex = Default.SoulIndex; //bring back to default settings
			return;
		}

		//check for mode param
		if ( (strcmp("rand", Param) == 0) || (strcmp("random", Param) == 0) )
			{Mode = M_Random; Activate(); return;}

		if ( (strcmp("min", Param) == 0) || (strcmp("first", Param) == 0) )
			{Mode = M_First; Activate(); return;}

		if ( (strcmp("phys", Param) == 0) || (strcmp("physical", Param) == 0) )
			{Mode = M_Physical; Activate(); return;}

		if ( (strcmp("ice", Param) == 0) )
			{Mode = M_Ice; Activate(); return;}

		if ( (strcmp("fire", Param) == 0) )
			{Mode = M_Fire; Activate(); return;}

		if ( (strcmp("poi", Param) == 0) || (strcmp("poison", Param) == 0) )
			{Mode = M_Poison; Activate(); return;}

		if ( (strcmp("ene", Param) == 0) || (strcmp("lightning", Param) == 0) )
			{Mode = M_Lightning; Activate(); return;}
		

		//we did not find a matching soul or mode
		Instigator.ClientMessage("Wrong param or monster: " $ Param);
		return;
	}

	iSoul = GetSoulIndex();
	if( iSoul >= 0 )
	    Instigator.ClientMessage("Using the " $ Default.ItemName $ " will consume the " $ InvSoul.SoulClasses[iSoul].Default.FriendlyName $ " soul.");
}

function int GetSoulIndex()
{
	local int i,j;
	local float BestResistance;
	local array<int> BestElements;
	local class<DWScriptedMonster> SelectedMonster;

	local array<int> StoredBestElements;
	local int iStored;
	local bool bHasNeededElement;


	if (Mode == M_First)
		return 0;


	for (i=0; i <= InvSoul.SoulClasses.length -1; i++)
	{
	    SelectedMonster = InvSoul.SoulClasses[i];
	    bHasNeededElement = false;

	    BestElements.length = 0;
	    BestResistance = SelectedMonster.default.PhysicalResistance;
    	    BestElements[0] = 0;

    	    if (SelectedMonster.default.FireResistance == BestResistance)
    		BestElements[BestElements.length] = 1;
    	    else if (SelectedMonster.default.FireResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.FireResistance;
		BestElements.length = 0;
		BestElements[0] = 1;
	    }
	
    	    if (SelectedMonster.default.ColdResistance == BestResistance)
		BestElements[BestElements.length] = 2;
    	    else if (SelectedMonster.default.ColdResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.ColdResistance;
		BestElements.length = 0;
		BestElements[0] = 2;
    	    }
	
    	    if (SelectedMonster.default.LightningResistance == BestResistance)
    		BestElements[BestElements.length] = 3;
    	    else if (SelectedMonster.default.LightningResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.LightningResistance;
		BestElements.length = 0;
		BestElements[0] = 3;
    	    }
	
    	    if (SelectedMonster.default.PoisonResistance == BestResistance)
		BestElements[BestElements.length] = 4;
    	    else if (SelectedMonster.default.PoisonResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.PoisonResistance;
		BestElements.length = 0;
		BestElements[0] = 4;
    	    }

	    Switch(Mode)
	    {
		case M_Random:
		    if (BestElements.length == 5)
		    {
			return i;
		    }
		    if ( (BestElements.length > 1) && (BestElements.length > StoredBestElements.length) )
		    {
			iStored = i;
			StoredBestElements.length = 0;
			for(j = 0; j < BestElements.length; j++)
			{
			    StoredBestElements[StoredBestElements.length] = BestElements[j];
			}
		    }

		    if ( (i >= int(round((InvSoul.SoulClasses.length - 1)*0.75))) && (StoredBestElements.length > 1) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Physical:
		    if (BestElements.length == 1 && BestElements[0] == 0)
		    {
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == 0)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }

		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Ice:
		    if (BestElements.length == 1 && BestElements[0] == 2)
		    {
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == 2)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }

		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Fire:
		    if (BestElements.length == 1 && BestElements[0] == 1)
		    {
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == 1)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }

		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Poison:
		    if (BestElements.length == 1 && BestElements[0] == 4)
		    {
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == 4)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }

		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Lightning:
		    if (BestElements.length == 1 && BestElements[0] == 3)
		    {
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == 3)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }

		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;
	    }
	}

	//fail
	Instigator.ClientMessage("No proper soul found or error");
	return -1;
}

function string GetFriendlyElements(array<int> Elements)
{
	local string ToReturn;
	local int i;

	ToReturn = "";
	for (i=0; i < Elements.length; i++)
	{
	    
	    Switch(Elements[i])
	    {
		case 0: ToReturn @= "Physical"; break;
		case 1: ToReturn @= "Fire"; break;
		case 2: ToReturn @= "Ice"; break;
		case 3: ToReturn @= "Lightning"; break;
		case 4: ToReturn @= "Poison"; break;
	    }
	}
	return ToReturn;
}

function class<DWScriptedMonster> GetMonsterclass(int MonsterIndex)
{
	if(MonsterIndex < 0)
		return None;
	return Super.GetMonsterclass(MonsterIndex);
}

defaultproperties
{
	ItemName="Silly Summon Skeletal Mage"
	MaxPressDelay=2
	Mode = M_First
}
I don't even know that I know nothing.
DW_Ant
DW Clan Member
Posts: 2670
Joined: Sat Jun 21, 2008 11:00 pm
Location: North Carolina

I'm in favor of this. I haven't studied the code yet, but at a glance, the GetSoulIndex function seems a bit cumbersome. It may make things harder to read and maintain. I'll definitely give this a shot locally, and I'll report any significant bugs if any.

One concern I have is that it could be complicating this ability too much for the players. I think if the default behavior summons a mage regardless of its resistances and without confirmation, we may be okay. But it may cause players some confusion if they accidentally hit alt activate instead of activate.
The difference between successful people from others is
not in the lack of strength,
not in the lack of knowledge,
but rather in the lack of will.

FFE466

_________________________
{F}{AH}{CivFR}{XC}{U}{DF}{CJ}{SD}
User avatar
Silly_Warlock
Killer in Training
Posts: 44
Joined: Tue Sep 17, 2013 8:56 am

It defaults to First Soul mode which always spawns and never asks for confirmation, also currently it's rather spammy with messages so on one hand it should be hard to 'get lost' but on the other hand it might be annoying. Made some small changes in code:

Made all elements into one case, changed enums order to fit the list of mage classes, added mode name to search fail message:

Code: Select all

class ArtifactSillySummonSkeletalMage extends ArtifactSummonSkeletalMage
	Config(MonsterAssaultRPG);

var enum EMode
{
	M_Physical,
	M_Fire,
	M_Ice,
	M_Lightning,
	M_Poison,
	M_First,
	M_Random
} Mode;

var int MaxPressDelay;
var int LastCancelledPressTime;
var bool bSpawnAnyways;
var bool bLastCancelled;


function Activate()
{
	bSpawnAnyways = false;
	if(bLastCancelled && Level.TimeSeconds - LastCancelledPressTime <= MaxPressDelay)
	    bSpawnAnyways = true;
	bLastCancelled = false;
	
	Super.Activate();
}

function AltActivate(optional string Param)
{
	local int i;
	local int iSoul;

	if (InvSoul == None || Instigator == None)
	{
		Destroy();
		return;
	}

    //Next mode
    if (Mode < EMode.EnumCount - 1)
	Mode = EMode(Mode+1);
    else
	Mode = EMode(0);
    Instigator.ClientMessage(GetEnum(Enum'EMode', Mode));

    if (Param != "")
    {
		//attempt to summon a monster with a soul matching this name
		for (i = 0; i < InvSoul.SoulClasses.length; i++)
		{
			if (strcmp(InvSoul.SoulClasses[i].Default.FriendlyName, Param) != 0)
				continue;

			//found a soul...summon this monster using this soul
			SoulIndex = i;
			Activate();
			SoulIndex = Default.SoulIndex; //bring back to default settings
			return;
		}

		//check for mode param
		if ( (strcmp("rand", Param) == 0) || (strcmp("random", Param) == 0) )
			{Mode = M_Random; Activate(); return;}

		if ( (strcmp("min", Param) == 0) || (strcmp("first", Param) == 0) )
			{Mode = M_First; Activate(); return;}

		if ( (strcmp("phys", Param) == 0) || (strcmp("physical", Param) == 0) )
			{Mode = M_Physical; Activate(); return;}

		if ( (strcmp("ice", Param) == 0) )
			{Mode = M_Ice; Activate(); return;}

		if ( (strcmp("fire", Param) == 0) )
			{Mode = M_Fire; Activate(); return;}

		if ( (strcmp("poi", Param) == 0) || (strcmp("poison", Param) == 0) )
			{Mode = M_Poison; Activate(); return;}

		if ( (strcmp("ene", Param) == 0) || (strcmp("lightning", Param) == 0) )
			{Mode = M_Lightning; Activate(); return;}
		

		//we did not find a matching soul or mode
		Instigator.ClientMessage("Wrong param or monster: " $ Param);
		return;
	}

	iSoul = GetSoulIndex();
	if( iSoul >= 0 )
	    Instigator.ClientMessage("Using the " $ Default.ItemName $ " will consume the " $ InvSoul.SoulClasses[iSoul].Default.FriendlyName $ " soul.");
}

function int GetSoulIndex()
{
	local int i,j;
	local float BestResistance;
	local array<int> BestElements;
	local class<DWScriptedMonster> SelectedMonster;

	local array<int> StoredBestElements;
	local int iStored;
	local bool bHasNeededElement;


	if (Mode == M_First)
		return 0;


	for (i=0; i <= InvSoul.SoulClasses.length -1; i++)
	{
	    SelectedMonster = InvSoul.SoulClasses[i];
	    bHasNeededElement = false;

	    BestElements.length = 0;
	    BestResistance = SelectedMonster.default.PhysicalResistance;
    	    BestElements[0] = 0;

    	    if (SelectedMonster.default.FireResistance == BestResistance)
    		BestElements[BestElements.length] = 1;
    	    else if (SelectedMonster.default.FireResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.FireResistance;
		BestElements.length = 0;
		BestElements[0] = 1;
	    }
	
    	    if (SelectedMonster.default.ColdResistance == BestResistance)
		BestElements[BestElements.length] = 2;
    	    else if (SelectedMonster.default.ColdResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.ColdResistance;
		BestElements.length = 0;
		BestElements[0] = 2;
    	    }
	
    	    if (SelectedMonster.default.LightningResistance == BestResistance)
    		BestElements[BestElements.length] = 3;
    	    else if (SelectedMonster.default.LightningResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.LightningResistance;
		BestElements.length = 0;
		BestElements[0] = 3;
    	    }
	
    	    if (SelectedMonster.default.PoisonResistance == BestResistance)
		BestElements[BestElements.length] = 4;
    	    else if (SelectedMonster.default.PoisonResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.PoisonResistance;
		BestElements.length = 0;
		BestElements[0] = 4;
    	    }

	    Switch(Mode)
	    {
		case M_Random:
		    //Best possible
		    if (BestElements.length == 5)
		    {
			return i;
		    }
		    //Store best available
		    if ( (BestElements.length > 1) && (BestElements.length > StoredBestElements.length) )
		    {
			iStored = i;
			StoredBestElements.length = 0;
			for(j = 0; j < BestElements.length; j++)
			{
			    StoredBestElements[StoredBestElements.length] = BestElements[j];
			}
		    }
		    //In last quarter return when passable soul available
		    if ( (i >= int(round((InvSoul.SoulClasses.length - 1)*0.75))) && (StoredBestElements.length > 1) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Physical: case M_Fire: case M_Ice: case M_Lightning: case M_Poison:
		    //Best possible
		    if (BestElements.length == 1 && BestElements[0] == Mode)
		    {   //last quarter
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    //Store best available
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == Mode)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }
		    //Last soul, return best
		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;
	    }
	}

	//fail
	Instigator.ClientMessage( "No proper soul found or error for mode:" @ GetEnum(Enum'EMode', Mode) );
	return -1;
}

function string GetFriendlyElements(array<int> Elements)
{
	local string ToReturn;
	local int i;

	ToReturn = "";
	for (i=0; i < Elements.length; i++)
	{
	    
	    Switch(Elements[i])
	    {
		case 0: ToReturn @= "Physical"; break;
		case 1: ToReturn @= "Fire"; break;
		case 2: ToReturn @= "Ice"; break;
		case 3: ToReturn @= "Lightning"; break;
		case 4: ToReturn @= "Poison"; break;
	    }
	}
	return ToReturn;
}

function class<DWScriptedMonster> GetMonsterclass(int MonsterIndex)
{
	if(MonsterIndex < 0)
		return None;
	return Super.GetMonsterclass(MonsterIndex);
}

defaultproperties
{
	ItemName="Silly Summon Skeletal Mage"
	MaxPressDelay=2
	Mode = M_First
}
I don't even know that I know nothing.
User avatar
Silly_Warlock
Killer in Training
Posts: 44
Joined: Tue Sep 17, 2013 8:56 am

Added param "default"- allows player to bind single key and both reliably activate to spawn something and have consistent starting point when iterating with alt activate.

Also fixed mode changing to next on alt activate even when parameter was given (parameters were working despite this).

Code: Select all

class ArtifactSillySummonSkeletalMage extends ArtifactSummonSkeletalMage
	Config(MonsterAssaultRPG);

var enum EMode
{
	M_Physical,
	M_Fire,
	M_Ice,
	M_Lightning,
	M_Poison,
	M_First,
	M_Random
} Mode;

var int MaxPressDelay;
var int LastCancelledPressTime;
var bool bSpawnAnyways;
var bool bLastCancelled;


function Activate()
{
	bSpawnAnyways = false;
	if(bLastCancelled && Level.TimeSeconds - LastCancelledPressTime <= MaxPressDelay)
	    bSpawnAnyways = true;
	bLastCancelled = false;
	
	Super.Activate();
}

function AltActivate(optional string Param)
{
	local int i;
	local int iSoul;

	if (InvSoul == None || Instigator == None)
	{
		Destroy();
		return;
	}

    //Next mode
    if (Param == "")
    {
	if (Mode < EMode.EnumCount - 1)
	    Mode = EMode(Mode+1);
	else
	    Mode = EMode(0);	
	Instigator.ClientMessage(GetEnum(Enum'EMode', Mode));
    }	

    if (Param != "")
    {
		//attempt to summon a monster with a soul matching this name
		for (i = 0; i < InvSoul.SoulClasses.length; i++)
		{
			if (strcmp(InvSoul.SoulClasses[i].Default.FriendlyName, Param) != 0)
				continue;

			//found a soul...summon this monster using this soul
			SoulIndex = i;
			Activate();
			SoulIndex = Default.SoulIndex; //bring back to default settings
			return;
		}

		//check for mode param

		if ( (strcmp("def", Param) == 0) || (strcmp("default", Param) == 0) )
		{
		    Mode = default.Mode;
 		    Instigator.ClientMessage(GetEnum(Enum'EMode', Mode));
 		    iSoul = GetSoulIndex();
 		    if( iSoul >= 0 )
			Instigator.ClientMessage("Using the " $ Default.ItemName $ " will consume the " $ InvSoul.SoulClasses[iSoul].Default.FriendlyName $ " soul.");
 		    return;
		}

		if ( (strcmp("rand", Param) == 0) || (strcmp("random", Param) == 0) )
			{Mode = M_Random; Activate(); return;}

		if ( (strcmp("min", Param) == 0) || (strcmp("first", Param) == 0) )
			{Mode = M_First; Activate(); return;}

		if ( (strcmp("phys", Param) == 0) || (strcmp("physical", Param) == 0) )
			{Mode = M_Physical; Activate(); return;}

		if ( (strcmp("ice", Param) == 0) )
			{Mode = M_Ice; Activate(); return;}

		if ( (strcmp("fire", Param) == 0) )
			{Mode = M_Fire; Activate(); return;}

		if ( (strcmp("poi", Param) == 0) || (strcmp("poison", Param) == 0) )
			{Mode = M_Poison; Activate(); return;}

		if ( (strcmp("ene", Param) == 0) || (strcmp("lightning", Param) == 0) )
			{Mode = M_Lightning; Activate(); return;}
		

		//we did not find a matching soul or mode
		Instigator.ClientMessage("Wrong param or monster: " $ Param);
		return;
	}

	iSoul = GetSoulIndex();
	if( iSoul >= 0 )
	    Instigator.ClientMessage("Using the " $ Default.ItemName $ " will consume the " $ InvSoul.SoulClasses[iSoul].Default.FriendlyName $ " soul.");
}

function int GetSoulIndex()
{
	local int i,j;
	local float BestResistance;
	local array<int> BestElements;
	local class<DWScriptedMonster> SelectedMonster;

	local array<int> StoredBestElements;
	local int iStored;
	local bool bHasNeededElement;


	if (Mode == M_First)
		return 0;


	for (i=0; i <= InvSoul.SoulClasses.length -1; i++)
	{
	    SelectedMonster = InvSoul.SoulClasses[i];
	    bHasNeededElement = false;

	    BestElements.length = 0;
	    BestResistance = SelectedMonster.default.PhysicalResistance;
    	    BestElements[0] = 0;

    	    if (SelectedMonster.default.FireResistance == BestResistance)
    		BestElements[BestElements.length] = 1;
    	    else if (SelectedMonster.default.FireResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.FireResistance;
		BestElements.length = 0;
		BestElements[0] = 1;
	    }
	
    	    if (SelectedMonster.default.ColdResistance == BestResistance)
		BestElements[BestElements.length] = 2;
    	    else if (SelectedMonster.default.ColdResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.ColdResistance;
		BestElements.length = 0;
		BestElements[0] = 2;
    	    }
	
    	    if (SelectedMonster.default.LightningResistance == BestResistance)
    		BestElements[BestElements.length] = 3;
    	    else if (SelectedMonster.default.LightningResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.LightningResistance;
		BestElements.length = 0;
		BestElements[0] = 3;
    	    }
	
    	    if (SelectedMonster.default.PoisonResistance == BestResistance)
		BestElements[BestElements.length] = 4;
    	    else if (SelectedMonster.default.PoisonResistance > BestResistance)
    	    {
		BestResistance = SelectedMonster.default.PoisonResistance;
		BestElements.length = 0;
		BestElements[0] = 4;
    	    }

	    Switch(Mode)
	    {
		case M_Random:
		    //Best possible
		    if (BestElements.length == 5)
		    {
			return i;
		    }
		    //Store best available
		    if ( (BestElements.length > 1) && (BestElements.length > StoredBestElements.length) )
		    {
			iStored = i;
			StoredBestElements.length = 0;
			for(j = 0; j < BestElements.length; j++)
			{
			    StoredBestElements[StoredBestElements.length] = BestElements[j];
			}
		    }
		    //In last quarter return when passable soul available
		    if ( (i >= int(round((InvSoul.SoulClasses.length - 1)*0.75))) && (StoredBestElements.length > 1) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;

		case M_Physical: case M_Fire: case M_Ice: case M_Lightning: case M_Poison:
		    //Best possible
		    if (BestElements.length == 1 && BestElements[0] == Mode)
		    {   //last quarter
			if(i >= int(round((InvSoul.SoulClasses.length - 1)*0.75)))
			{
			    if(bSpawnAnyways)
			    	return i;
			    Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
			    Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			    LastUseTime = -1;
			    bLastCancelled = true;
			    LastCancelledPressTime = Level.TimeSeconds;
			    return -1;
			}
			return i;
		    }
		    //Store best available
		    if ( (BestElements.length < 5) &&((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
		    {
			for(j = 0; j < BestElements.length; j++)
			{
			    if (BestElements[j] == Mode)
				bHasNeededElement = true;
			}
			if (bHasNeededElement)
			{
			    iStored = i;
			    StoredBestElements.length = 0;
			    for(j = 0; j < BestElements.length; j++)
			    {
				StoredBestElements[StoredBestElements.length] = BestElements[j];
			    }
			}
		    }
		    //Last soul, return best
		    if ( (i == (InvSoul.SoulClasses.length - 1)) && (StoredBestElements.length < 5) && (StoredBestElements.length > 0) )
		    {
			if(bSpawnAnyways)
			    return iStored;
			Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
			Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		    }
		break;
	    }
	}

	//fail
	Instigator.ClientMessage( "No proper soul found or error for mode:" @ GetEnum(Enum'EMode', Mode) );
	return -1;
}

function string GetFriendlyElements(array<int> Elements)
{
	local string ToReturn;
	local int i;

	ToReturn = "";
	for (i=0; i < Elements.length; i++)
	{
	    
	    Switch(Elements[i])
	    {
		case 0: ToReturn @= "Physical"; break;
		case 1: ToReturn @= "Fire"; break;
		case 2: ToReturn @= "Ice"; break;
		case 3: ToReturn @= "Lightning"; break;
		case 4: ToReturn @= "Poison"; break;
	    }
	}
	return ToReturn;
}

function class<DWScriptedMonster> GetMonsterclass(int MonsterIndex)
{
	if(MonsterIndex < 0)
		return None;
	return Super.GetMonsterclass(MonsterIndex);
}

defaultproperties
{
	ItemName="Silly Summon Skeletal Mage"
	MaxPressDelay=2
	Mode = M_First
}
I don't even know that I know nothing.
DW_Ant
DW Clan Member
Posts: 2670
Joined: Sat Jun 21, 2008 11:00 pm
Location: North Carolina

I've looked into your changes, and I find this very useful to have. I've updated skeletal mage ability to use your artifact instead of mine. However, doing so would result in two bindable artifacts in the artifact configuration order. I did remove my artifact from the list, but players that have already configured their artifacts would have two Summon Skeletal Magii in their list still. I can leave it as is, or merge your artifact with summon skeletal mage, or nuke client's artifact configuration (not preferred).

I've also made the following changes:
  • Mode commands are processed before the for loop to avoid having to iterate through souls if it's a predetermined command.
  • Implemented a help command that describes each mode/command.
  • Fixed random mode where it exit early if when it reached the last quarter of soul pool.
  • Threshold for confirmation prompt is based on the selected soul's scoring value instead of based on soul position on soul pool position. The soul must have at least 10 scoring value for 2 sec confirmation prompt.
Here's what I have. What are your thoughts?

Code: Select all

class ArtifactSillySummonSkeletalMage extends ArtifactSummonSkeletalMage
   Config(MonsterAssaultRPG);

var enum EMode
{
   M_Physical,
   M_Fire,
   M_Ice,
   M_Lightning,
   M_Poison,
   M_First,
   M_Random
} Mode;

var int MaxPressDelay;
var int LastCancelledPressTime;
var bool bSpawnAnyways;
var bool bLastCancelled;


function Activate()
{
	bSpawnAnyways = false;
	if(bLastCancelled && Level.TimeSeconds - LastCancelledPressTime <= MaxPressDelay)
	{
		bSpawnAnyways = true;
	}

	bLastCancelled = false;
   
	Super.Activate();
}

function AltActivate(optional string Param)
{
	local int i;
	local int iSoul;

	if (InvSoul == None || Instigator == None)
	{
		Destroy();
		return;
	}

	//Next mode
	if (Param == "")
	{
		if (Mode < EMode.EnumCount - 1)
		{
			Mode = EMode(Mode+1);
		}
		else
		{
			Mode = EMode(0); 
		}

		Instigator.ClientMessage(GetEnum(Enum'EMode', Mode));
	}   

	if (Param != "")
	{
		//check for mode param
		if ( (strcmp("def", Param) == 0) || (strcmp("default", Param) == 0) )
		{
			Mode = default.Mode;
			Instigator.ClientMessage(GetEnum(Enum'EMode', Mode));
			iSoul = GetSoulIndex();
			if( iSoul >= 0 )
				Instigator.ClientMessage("Using the " $ Default.ItemName $ " will consume the " $ InvSoul.SoulClasses[iSoul].Default.FriendlyName $ " soul.");
			return;
		}

		if ( (strcmp("rand", Param) == 0) || (strcmp("random", Param) == 0) )
			{Mode = M_Random; Activate(); return;}

		if ( (strcmp("min", Param) == 0) || (strcmp("first", Param) == 0) )
			{Mode = M_First; Activate(); return;}

		if ( (strcmp("phys", Param) == 0) || (strcmp("physical", Param) == 0) || strcmp("cyclone", param) == 0)
			{Mode = M_Physical; Activate(); return;}

		if ( (strcmp("ice", Param) == 0) || (strcmp("cold", Param) == 0) || (strcmp("frozen", Param) == 0))
			{Mode = M_Ice; Activate(); return;}

		if ( (strcmp("fire", Param) == 0) || (strcmp("burning", Param) == 0))
			{Mode = M_Fire; Activate(); return;}

		if ( (strcmp("poi", Param) == 0) || (strcmp("poison", Param) == 0) || (strcmp("toxic", Param) == 0))
			{Mode = M_Poison; Activate(); return;}

		if ( (strcmp("ene", Param) == 0) || (strcmp("lightning", Param) == 0) || (strcmp("electric", Param) == 0))
			{Mode = M_Lightning; Activate(); return;}

		if (Param ~= "help")
		{
			Instigator.ClientMessage("\"def\" or \"default\":  resets summon priority to default mode, which is " $ GetEnum(Enum'EMode', Default.Mode));
			Instigator.ClientMessage("\"rand\" or \"random\":  attempts to consume the soul that has the most possible elements.");
			Instigator.ClientMessage("\"min\" or \"first\":  attempts to summon a skeletal mage using the weakest soul.");
			Instigator.ClientMessage("\"phys\" or \"physical\":  attempts to summon a cyclone skeletal mage.");
			Instigator.ClientMessage("\"ice\" or \"cold\" or \"frozen\":  attempts to summon a frozen skeletal mage.");
			Instigator.ClientMessage("\"fire\" or \"burning\":  attempts to summon a burning skeletal mage.");
			Instigator.ClientMessage("\"poi\" or \"poison\" or \"toxic\":  attempts to summon a toxic skeletal mage.");
			Instigator.ClientMessage("\"ene\" or \"lightning\" or \"electric\":  attempts to summon an electric skeletal mage.");
			Instigator.ClientMessage("<Other Name>:  attempts to use a soul of matching name to summon a skeletal mage.");
			Instigator.ClientMessage("\"\":  alternates summon priority mode.");
			return;
		}

		//attempt to summon a monster with a soul matching this name
		for (i = 0; i < InvSoul.SoulClasses.length; i++)
		{
			if (strcmp(InvSoul.SoulClasses[i].Default.FriendlyName, Param) != 0)
				continue;

			//found a soul...summon this monster using this soul
			SoulIndex = i;
			Activate();
			SoulIndex = Default.SoulIndex; //bring back to default settings
			return;
		}
      

		//we did not find a matching soul or mode
		Instigator.ClientMessage("You do not possess a: " $ Param);
		return;
	}

	iSoul = GetSoulIndex();
	if (iSoul >= 0)
	{
		Instigator.ClientMessage("Using the " $ Default.ItemName $ " will consume the " $ InvSoul.SoulClasses[iSoul].Default.FriendlyName $ " soul.");
	}
}

/**
 * Returns true if the specified soul should prompt the user for confirmation before consumption.
 */
function bool IsStrongSoul (int SoulIndex)
{
	if (SoulIndex >= 0 && SoulIndex < InvSoul.SoulClasses.Length)
	{
		return (InvSoul.SoulClasses[SoulIndex].Default.ScoringValue >= 10);
	}

	return false;
}

function int GetTotalNumTiedBestResistance (class<DWScriptedmonster> MonsterClass)
{
	local int BestResistance;
	local int Result;

	Result = 1;
	BestResistance = MonsterClass.Default.PhysicalResistance;
	if (MonsterClass.Default.FireResistance == BestResistance)
	{
		Result++;
	}
	else if (MonsterClass.Default.FireResistance > BestResistance)
	{
		BestResistance = MonsterClass.Default.FireResistance;
		Result = 1;
	}

	if (MonsterClass.Default.ColdResistance == BestResistance)
	{
		Result++;
	}
	else if (MonsterClass.Default.ColdResistance > BestResistance)
	{
		BestResistance = MonsterClass.Default.ColdResistance;
		Result = 1;
	}

	if (MonsterClass.Default.LightningResistance == BestResistance)
	{
		Result++;
	}
	else if (MonsterClass.Default.LightningResistance > BestResistance)
	{
		BestResistance = MonsterClass.Default.LightningResistance;
		Result = 1;
	}

	if (MonsterClass.Default.PoisonResistance == BestResistance)
	{
		Result++;
	}
	else if (MonsterClass.Default.PoisonResistance > BestResistance)
	{
		return 1;
	}

	return Result;
}

function int GetSoulIndex()
{
	local int i, j;

	local int BestSoul;
	local int BestNumResistances;
	local int NumTiedResistances;

	local float BestResistance;
	local array<int> BestElements;
	local class<DWScriptedMonster> SelectedMonster;

	local array<int> StoredBestElements;
	local int iStored;
	local bool bHasNeededElement;

	if (Mode == M_First)
	{
		return 0;
	}

	if (Mode == M_Random)
	{
		BestSoul = -1;
		BestNumResistances = 1; //Must have at least 2 tied resistances to be considered
		for (i = 0; i < InvSoul.SoulClasses.Length; i++)
		{
			NumTiedResistances = GetTotalNumTiedBestResistance(InvSoul.Soulclasses[i]);
			if (NumTiedResistances > BestNumResistances)
			{
				BestSoul = i;
				BestNumResistances = NumTiedResistances;

				if (BestNumResistances >= 5)
				{
					break; //Can't get any better than 5 [phys, fire, cold, lightning, poison].
				}
			}
		}

		if (BestSoul < 0)
		{
			Instigator.ClientMessage("You do not possess a soul with diverse elemental resistances.");
			return -1;
		}

		//In last quarter return when passable soul available
		if (IsStrongSoul(BestSoul))
		{
			if(bSpawnAnyways)
			{
				return BestSoul;
			}

			Instigator.ClientMessage("Best soul found: " $ InvSoul.SoulClasses[BestSoul].Default.FriendlyName $ " With these elements: " $ GetElementsFromMonster(InvSoul.SoulClasses[BestSoul]));
			Instigator.ClientMessage("Activate within " $ MaxPressDelay $ " seconds to spawn anyways.");
			LastUseTime = -1;
			bLastCancelled = true;
			LastCancelledPressTime = Level.TimeSeconds;
			return -1;
		}

		return BestSoul;
	}

	for (i=0; i < InvSoul.SoulClasses.length; i++)
	{
		SelectedMonster = InvSoul.SoulClasses[i];
		bHasNeededElement = false;

		BestElements.length = 0;
		BestResistance = SelectedMonster.default.PhysicalResistance;
		BestElements[0] = 0;

		if (SelectedMonster.default.FireResistance == BestResistance)
		{
			BestElements[BestElements.length] = 1;
		}
		else if (SelectedMonster.default.FireResistance > BestResistance)
		{
			BestResistance = SelectedMonster.default.FireResistance;
			BestElements.length = 0;
			BestElements[0] = 1;
		}
   
		if (SelectedMonster.default.ColdResistance == BestResistance)
		{
			BestElements[BestElements.length] = 2;
		}
		else if (SelectedMonster.default.ColdResistance > BestResistance)
		{
			BestResistance = SelectedMonster.default.ColdResistance;
			BestElements.length = 0;
			BestElements[0] = 2;
		}
   
		if (SelectedMonster.default.LightningResistance == BestResistance)
		{
			BestElements[BestElements.length] = 3;
		}
		else if (SelectedMonster.default.LightningResistance > BestResistance)
		{
			BestResistance = SelectedMonster.default.LightningResistance;
			BestElements.length = 0;
			BestElements[0] = 3;
		}
   
		if (SelectedMonster.default.PoisonResistance == BestResistance)
		{
			BestElements[BestElements.length] = 4;
		}
		else if (SelectedMonster.default.PoisonResistance > BestResistance)
		{
			BestResistance = SelectedMonster.default.PoisonResistance;
			BestElements.length = 0;
			BestElements[0] = 4;
		}

		Switch(Mode)
		{
			case M_Physical: case M_Fire: case M_Ice: case M_Lightning: case M_Poison:
				//Best possible
				if (BestElements.length == 1 && BestElements[0] == Mode)
				{
					if (IsStrongSoul(i))
					{
						if(bSpawnAnyways)
							return i;
						Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[i].Default.FriendlyName$" With these elements: "$GetFriendlyElements(BestElements));
						Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
						LastUseTime = -1;
						bLastCancelled = true;
						LastCancelledPressTime = Level.TimeSeconds;
						return -1;
					}

					return i;
				}

				//Store best available
				if ( (BestElements.length < 5) && ((BestElements.length < StoredBestElements.length) || (StoredBestElements.length == 0)) )
				{
					for(j = 0; j < BestElements.length; j++)
					{
						if (BestElements[j] == Mode)
						{
							bHasNeededElement = true;
						}
					}
					if (bHasNeededElement)
					{
						iStored = i;
						StoredBestElements.length = 0;
						for(j = 0; j < BestElements.length; j++)
						{
							StoredBestElements[StoredBestElements.length] = BestElements[j];
						}
					}
				}

				//Last soul, return best
				if ( i == (InvSoul.SoulClasses.length - 1) && StoredBestElements.length < 5 && StoredBestElements.length > 0)
				{
					if(bSpawnAnyways)
						return iStored;
					Instigator.ClientMessage("Best soul found: "$InvSoul.SoulClasses[iStored].Default.FriendlyName$" With these elements: "$GetFriendlyElements(StoredBestElements));
					Instigator.ClientMessage("Activate within "$MaxPressDelay$" seconds to spawn anyways.");
					LastUseTime = -1;
					bLastCancelled = true;
					LastCancelledPressTime = Level.TimeSeconds;
					return -1;
				}
				break; //break switch statement
       }
   }

   //fail
   Instigator.ClientMessage( "No proper soul found for mode:" @ GetEnum(Enum'EMode', Mode) );
   return -1;
}

function string GetElementsFromMonster (class<DWScriptedMonster> MonsterClass)
{
	local array<int> BestElements;
	local int BestResistance;

	BestElements[0] = 0;
	BestResistance = MonsterClass.Default.PhysicalResistance;
	if (MonsterClass.Default.FireResistance == BestResistance)
	{
		BestElements[BestElements.Length] = 1;
	}
	else if (MonsterClass.Default.FireResistance > BestResistance)
	{
		BestElements.Length = 0;
		BestElements[0] = 1;
		BestResistance = MonsterClass.Default.FireResistance;
	}

	if (MonsterClass.Default.ColdResistance == BestResistance)
	{
		BestElements[BestElements.Length] = 2;
	}
	else if (MonsterClass.Default.ColdResistance > BestResistance)
	{
		BestElements.Length = 0;
		BestElements[0] = 2;
		BestResistance = MonsterClass.Default.ColdResistance;
	}

	if (MonsterClass.Default.LightningResistance == BestResistance)
	{
		BestElements[BestElements.Length] = 3;
	}
	else if (MonsterClass.Default.LightningResistance > BestResistance)
	{
		BestElements.Length = 0;
		BestElements[0] = 3;
		BestResistance = MonsterClass.Default.LightningResistance;
	}

	if (MonsterClass.Default.PoisonResistance == BestResistance)
	{
		BestElements[BestElements.Length] = 4;
	}
	else if (MonsterClass.Default.PoisonResistance > BestResistance)
	{
		BestElements.Length = 0;
		BestElements[0] = 4;
		BestResistance = MonsterClass.Default.PoisonResistance;
	}

	return GetFriendlyElements(BestElements);
}

function string GetFriendlyElements(array<int> Elements)
{
   local string ToReturn;
   local int i;

   ToReturn = "";
   for (i=0; i < Elements.length; i++)
   {
      
       Switch(Elements[i])
       {
      case 0: ToReturn @= "Physical"; break;
      case 1: ToReturn @= "Fire"; break;
      case 2: ToReturn @= "Ice"; break;
      case 3: ToReturn @= "Lightning"; break;
      case 4: ToReturn @= "Poison"; break;
       }
   }
   return ToReturn;
}

function class<DWScriptedMonster> GetMonsterclass (int MonsterIndex)
{
	if(MonsterIndex < 0)
		return None;
	return Super.GetMonsterclass(MonsterIndex);
}

defaultproperties
{
	ItemName="Summon Skeletal Mage"
	MaxPressDelay=2
	Mode = M_First
}
The difference between successful people from others is
not in the lack of strength,
not in the lack of knowledge,
but rather in the lack of will.

FFE466

_________________________
{F}{AH}{CivFR}{XC}{U}{DF}{CJ}{SD}
User avatar
Silly_Warlock
Killer in Training
Posts: 44
Joined: Tue Sep 17, 2013 8:56 am

I believe that the most sensible option is to merge my changes to existing artifact.

As for your changes- my only qualm is that while I believe your threshold check is more relevant it seems to me that it won't account for context and use up best souls possibly meant for another use (like shout and tainted).
I don't even know that I know nothing.
DW_Wraith
DW Clan Member
Posts: 846
Joined: Sun Jan 08, 2006 12:00 am

Sounds very cool.
Post Reply