mirror of
https://github.com/Jusctsch5/ironsphererpg.git
synced 2026-01-19 19:44:45 +00:00
Taking everything obtained from http://ironsphererpg2.webs.com/ and dumping it in a git repo
489 lines
14 KiB
C#
489 lines
14 KiB
C#
$numspawnpoints = 0;
|
|
function createAISpawn(%pos, %box, %mindelay, %maxdelay, %botlist, %team, %attack, %zone)
|
|
{
|
|
$AIspawn::spawnPoint[$numspawnpoints] = %pos;//transform..
|
|
$AIspawn::spawnBox[$numspawnPoints] = %box;
|
|
$AIspawn::mindelay[$numspawnpoints] = %mindelay;
|
|
$AIspawn::maxdelay[$numspawnpoints] = %maxdelay;
|
|
$AIspawn::List[$numspawnpoints] = %botlist;
|
|
$AIspawn::Team[$numspawnpoints] = %team;
|
|
$AIspawn::Attack[$numspawnpoints] = %attack;
|
|
$AISpawn::needsSpawn[$numspawnpoints] = 1;
|
|
|
|
// if($debugMode)
|
|
//echo("-spawning("@%pos@","@%box@","@%mindelay@","@%maxdelay@","@%botlist@","@%team@","@%attack %zone@")");
|
|
|
|
//if($debugMode) echo("spawnbot(" @ %index @ ", " @ %si @ ")");
|
|
|
|
$numspawnpoints++;
|
|
}
|
|
|
|
function GameConnection::deSpawn(%client)
|
|
{
|
|
if(!%client.isAiControlled())
|
|
return;
|
|
|
|
%client.despawning = true;
|
|
%client.player.setPosition("0 0 -1000");
|
|
%client.player.schedule(500, "delete");
|
|
%client.schedule(10, "drop");
|
|
}
|
|
|
|
function InitSpawnPoints()
|
|
{
|
|
if($rules !$="dm")
|
|
{
|
|
DefineLoadouts();
|
|
for(%i = 1; $SpawnIndex[%i] !$= ""; %i++)
|
|
{
|
|
$aistack[%i] = initstack();
|
|
}
|
|
DefineAISpawn();
|
|
for(%i = 0; %i < $numspawnpoints; %i++)
|
|
{
|
|
$numaiperspawnpoint[%i] = 0;
|
|
Game.SpawnLoop(%i);
|
|
}
|
|
echo("Initialized " @ %i @ " spawn points.");
|
|
}
|
|
//aisystemenabled(true);
|
|
|
|
}
|
|
|
|
function shouldAIBeAt(%pos)
|
|
{
|
|
%dist = 200;
|
|
for(%i = 0; %i < ClientGroup.getCount(); %i++)
|
|
{
|
|
%cl = ClientGroup.getObject(%i);
|
|
if(%cl.isAIControlled())
|
|
continue;
|
|
|
|
if(isObject(%cl.player))
|
|
{
|
|
if(VectorDist(%cl.player.getWorldBoxCenter(), %pos) < %dist)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function RPGGame::SpawnLoop(%game, %index)
|
|
{
|
|
if($serverallowinfinitespawn)
|
|
$numAIperSpawnPoint[%index] = 0;
|
|
%transform = $AIspawn::SpawnPoint[%index];
|
|
%mindelay = $AIspawn::mindelay[%index];
|
|
%maxdelay = $AIspawn::maxdelay[%index];
|
|
%diff = %maxdelay - %mindelay;
|
|
%delay = mfloor(getRandom() * %diff) + %mindelay;
|
|
|
|
if($numaiperspawnpoint[%index] < 0)
|
|
$numaiperspawnpoint[%index] = 0;
|
|
|
|
%zone = positionInWhichZone($AIspawn::spawnPoint[%index]);
|
|
if(!shouldAIBeAt($AIspawn::SpawnPoint[%index]))
|
|
{
|
|
%game.schedule(1000, "SpawnLoop", %index);
|
|
return;
|
|
}
|
|
|
|
if($spawnMultiplier == 0) %flag = false;
|
|
|
|
if($numaiperspawnpoint[%index] == 0)
|
|
{
|
|
//determine %bottype based on indexes
|
|
|
|
for(%i = 0; getword($aispawn::list[%index], %i) !$= ""; %i++)
|
|
{
|
|
}
|
|
|
|
%randpick = getRPGroll("1r" @ %i);
|
|
// console spam fix
|
|
//echo("%randpick = " @ %randpick @ "| %i = " @ %i);
|
|
%randpick--;
|
|
%randpick = GetWord($aiSpawn::list[%index], %randpick);
|
|
if(%randpick !$= "")
|
|
%client = %Game.SpawnBot(%index, %randpick);
|
|
|
|
//spawn successful!
|
|
if(isObject(%client))
|
|
{
|
|
%client.homeZone = %zone;
|
|
|
|
if($AIspawn::Attack[%index] > 0)
|
|
{
|
|
|
|
$aiAttack[%client] = $AIspawn::Attack[%index];
|
|
//echo("Spawn: Attack pos->" SPC $aiAttack[%client] SPC $AIspawn::Attack[%index]);
|
|
}
|
|
|
|
$numAIperSpawnPoint[%index]++;
|
|
%client.mySpawnPoint = %index;
|
|
}
|
|
else
|
|
error("Error spawning bot at spawnPoint index " @ %index);
|
|
}
|
|
//always call back the spawn loop, in case a spot is freed up for a helper to spawn
|
|
%game.schedule(%delay * 1000, "SpawnLoop", %index);
|
|
|
|
}
|
|
|
|
function RPGGame::SpawnBot(%game, %index, %si)
|
|
{
|
|
if($debugMode) echo("spawnbot(" @ %index @ ", " @ %si @ ")");
|
|
%spawnPoint = $AIspawn::SpawnPoint[%index];
|
|
%name = GenerateName(%si);
|
|
%race = $aiRace[$spawnIndex[%si]];
|
|
%raceId = $RaceID[%race];
|
|
|
|
if($DebugMode) echo("-spawned("@%spawnPoint@","@%name@","@%race@","@%raceId@")");
|
|
|
|
//if ($DebugMode) echo("spawnTownbot(" @ %pos @ ", " @ %team @ ", " @ %type @ ", " @ %race @ ", " @ %shop @ ", " @ %name @ ")");
|
|
|
|
//if($debugMode)
|
|
//echo( this.%pos this.%box this.%mindelay this.%maxdelay this.%botlist this.%team this.%attack this.%zone );
|
|
//echo(
|
|
if($aistack[%si].empty())
|
|
{
|
|
//if the race's stack is empty connect a new AI
|
|
%ai = aiConnect(%name, %si);
|
|
//create its data field
|
|
%ai.data = new ScriptObject();
|
|
}
|
|
else
|
|
{
|
|
|
|
%ai = $aistack[%si].pop();//take a used ai off the stack for play.
|
|
%ai.data.delete();//whoops RESET player.
|
|
%ai.data = new ScriptObject();
|
|
|
|
}
|
|
if(isObject(%ai))
|
|
{
|
|
Game.AIHasJoined(%ai);
|
|
|
|
//bah hardcode this part
|
|
for(%i = 0; Getword($enemyprofile[$SpawnIndex[%si]], %i) !$= ""; %i += 2)
|
|
{
|
|
%w = Getword($enemyprofile[$SpawnIndex[%si]], %i);
|
|
%w2 = Getword($enemyprofile[$SpawnIndex[%si]], %i+1);
|
|
|
|
if(%w $= "LVL")
|
|
{
|
|
%lvl = getRPGroll(%w2);
|
|
storeData(%ai, "tempLVL", %lvl);
|
|
StoreData(%ai, "EXP", (%lvl-1)*1000);
|
|
}
|
|
else if(%w $= "COINS")
|
|
{
|
|
storedata(%ai, "COINS", GetRPGRoll(%w2));
|
|
}
|
|
else if(%w $= "CLASS")
|
|
{
|
|
storeData(%ai, "CLASS", %w2);
|
|
storeData(%ai, "GROUP", $ClassGroup[fetchData(%client, "CLASS")]);
|
|
}
|
|
|
|
}
|
|
storeData(%ai, "RACE", %race);
|
|
storeData(%ai, "SpawnIndex", %si);
|
|
storedata(%ai, "attb", $attb[$SpawnIndex[%si]]);//attack behavior?
|
|
storedata(%ai, "magic", $bot::magic[$SpawnIndex[%si]]);//can use magic?
|
|
%ai.weight = 0;
|
|
HardcodeAIskills(%ai);
|
|
//GiveThisStuff(%id, $EnemyProfile[%si]);
|
|
%ai.team = $AISpawn::Team[%index];
|
|
//%ai.team = 1;
|
|
if($RaceSkin[%raceid] !$="")
|
|
{
|
|
%client.skin = $raceSkin[%raceid];// should work
|
|
setTargetSkin(%client.target, %client.skin);
|
|
}
|
|
%armor = fetchData(%ai, "RACE") @ "Armor";
|
|
//%armor = "D";
|
|
//echo(%armor);
|
|
|
|
// console spam fix
|
|
switch$(%armor)
|
|
{
|
|
case "MaleOrcArmor": %fish = false;
|
|
case "MaleHumanArmor":%fish = false;
|
|
case "OrcArmor": %fish = false;
|
|
case "GoblinArmor":%armor = "MaleOrcArmor"; %fish = false;
|
|
case "FishArmor":%fish = true;
|
|
case "GnollArmor": %fish = false;
|
|
case "ElementalArmor": %fish = false;
|
|
case "MaleElfArmor": %armor = "ElfArmor";
|
|
case "ElfArmor": %fish = false;
|
|
case "MinotaurArmor": %fish = false;
|
|
case "OgreArmor": %fish = false;
|
|
default: %armor = "MaleHumanArmor";%fish = false;
|
|
}
|
|
//echo(%armor);
|
|
%ai.armor = %armor;
|
|
//echo(%armor.scale);
|
|
%player = new Player()
|
|
{
|
|
dataBlock = %armor;
|
|
|
|
};
|
|
|
|
%player.setDataBlock(%armor);//lets try this
|
|
|
|
%minrad = %spawnpoint @ " 1 0 0 0";
|
|
|
|
%rad = getword(%spawnpoint, 0) + getrandom() * getword($AIspawn::box[%index],0) SPC getword(%spawnpoint, 1) + getrandom() * getword($AIspawn::box[%index],1) SPC getword(%spawnpoint, 2) + getrandom() * getword($AIspawn::box[%index],2);
|
|
//echo(%spawnloc);
|
|
|
|
%c = containerRayCast(%rad, vectorAdd(%rad, "0 0 -100"), $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType, 0);
|
|
|
|
%rad = posFromRaycast(%c);
|
|
|
|
%player.setTransform(%rad @ " 1 0 0 0");
|
|
%player.startFade(0,0,1);
|
|
MissionCleanup.add(%player);
|
|
%player.setVelocity("0 0 -1");
|
|
|
|
//*PHANTOM139 : Spawn effect call
|
|
BotSpawnEffects(%player);
|
|
//
|
|
|
|
%player.setOwnerClient(%ai);
|
|
%player.team = %ai.team;
|
|
%ai.player = %player;
|
|
%player.startFade(1000,0,0);
|
|
//make sure the player object is the AI's control object - even during the mission warmup time
|
|
//the function AISystemEnabled(true/false) will control whether they actually move...
|
|
%ai.setControlObject(%ai.player);
|
|
|
|
//clear the objective and choose a new one
|
|
AIUnassignClient(%ai);
|
|
%ai.stop();
|
|
%ai.clearStep();
|
|
%ai.lastDamageClient = -1;
|
|
%ai.lastDamageTurret = -1;
|
|
%ai.setEngageTarget(-1);
|
|
%ai.setTargetObject(-1);
|
|
%ai.pilotVehicle = false;
|
|
%ai.isfish = %fish;
|
|
//set the spawn time
|
|
%ai.spawnTime = getSimTime();
|
|
%ai.respawnThread = "";
|
|
if(%ai.respawnTimer)
|
|
cancel(%ai.respawnTimer);
|
|
%ai.observerStartTime = "";
|
|
%ai.camera.mode = "";
|
|
// updates client's target info for this player
|
|
UpdateTargetStuff(%ai);
|
|
//--- temp until loadchar comes in
|
|
setHP(%ai, fetchData(%ai, "MaxHP"));
|
|
setMANA(%ai, fetchData(%ai, "MaxMANA"));
|
|
//storeData(%client, "templvl", GetLevel(fetchData(%client, "EXP")));
|
|
//----
|
|
|
|
storeData(%ai, "HasLoadedAndSpawned", true);
|
|
//timeslice the objective reassessment for the bots
|
|
if(!isEventPending(%ai.objectiveThread))
|
|
{
|
|
%curTime = getSimTime();
|
|
%remainder = %curTime % 5000;
|
|
%schedTime = $AITimeSliceReassess - %remainder;
|
|
if (%schedTime <= 0)
|
|
%schedTime += 5000;
|
|
%ai.objectiveThread = schedule(%schedTime, %ai, "AIReassessObjective", %ai);
|
|
|
|
//set the next time slice "slot"
|
|
$AITimeSliceReassess += 300;
|
|
if ($AITimeSliceReassess > 5000)
|
|
$AITimeSliceReassess -= 5000;
|
|
}
|
|
|
|
if(!%fish)
|
|
{
|
|
%ai.rpgAttackTask = %ai.addTask(AIRPGAttackTask);
|
|
%ai.rpgWanderTask = %ai.addTask(AIRPGWanderTask);
|
|
%ai.rpgSelectWeaponTask = %ai.addTask(AIRPGSelectWeaponTask);
|
|
|
|
}
|
|
else
|
|
{
|
|
%ai.rpgFishWanderTask = %ai.addTask(AIRPGFishWanderTask);
|
|
//%ai.voice = "";
|
|
//%ai.voiceTag = "";// lets try this
|
|
}
|
|
$ainumber++;
|
|
%ai.rpgName = %name @ " Bot";
|
|
%ai.namebase = %name;
|
|
%ai.mySpawnPoint = %index;
|
|
//clear the inventory
|
|
ClearInventory(%ai);
|
|
%ai.equiplist = "";
|
|
for(%i = 0; GetWord($EnemyWeapons[%si],%i) !$= ""; %i = %i+3)
|
|
{
|
|
%weapon = GetWord($enemyWeapons[%si],%i);
|
|
|
|
%pre = GetWord($enemyWeapons[%si],%i+1);
|
|
%suff = GetWord($enemyWeapons[%si],%i+2);
|
|
//echo("%weapon = " @ %weapon SPC "%pre = " @ %pre SPC "%suff =" SPC %suff SPC "%equipped =" SPC (%i == 0));
|
|
AddToInventory(%ai, 1, %weapon, %pre, %suff, (%i == 0));
|
|
}
|
|
for(%i = 0; GetWord($EnemyArmors[%si],%i) !$= ""; %i = %i+3)
|
|
{
|
|
%earmor = GetWord($EnemyArmors[%si],%i);
|
|
%pre = GetWord($EnemyArmors[%si],%i+1);
|
|
%suff = GetWord($EnemyArmors[%si],%i+2);
|
|
AddToInventory(%ai, 1, %earmor, %pre, %suff, false);
|
|
}
|
|
for(%i = 0; GetWord($EnemyItems[%si],%i) !$= ""; %i = %i+3)
|
|
{
|
|
%item = GetWord($EnemyItems[%si],%i);
|
|
%roll1 = GetWord($EnemyItems[%si],%i+1);
|
|
%roll2 = GetWord($EnemyItems[%si],%i+2);
|
|
%roll1 = GetRPGroll(%roll1);
|
|
if(GetRPGroll(%roll2) == 1)
|
|
AddToInventory(%ai, %roll1, %item, 0, 0, false);
|
|
}
|
|
//setup stats etc
|
|
refreshall(%ai);
|
|
//echo(%armor);
|
|
if(%armor $= "ElementalArmor")
|
|
{
|
|
%player.setCloaked(true);
|
|
loopshieldeffect(%player);
|
|
}
|
|
}
|
|
|
|
return %ai;
|
|
}
|
|
function loopshieldeffect(%player)
|
|
{
|
|
%player.playshieldeffect(getvector(%player));
|
|
schedule(1000,%player, loopshieldeffect, %player);
|
|
}
|
|
function GenerateName(%si)
|
|
{
|
|
|
|
return $SpawnIndex[%si];
|
|
}
|
|
|
|
function RandomTransform(%trans, %minrad, %maxrad)
|
|
{
|
|
%tempPos = RandomPositionXY(%minrad, %maxrad);
|
|
%xPos = GetWord(%tempPos, 0) + GetWord(%trans, 0);
|
|
%yPos = GetWord(%tempPos, 1) + GetWord(%trans, 1);
|
|
%zPos = GetTerrainHeight(%xPos SPC %ypos);
|
|
|
|
%newtrans = %xPos SPC %yPos SPC %zPos SPC GetWords(%trans, 3, 6);
|
|
}
|
|
//merchants etc.. non ai bots...
|
|
|
|
function spawnTownBot(%pos, %team, %type, %race , %shop , %name)
|
|
{
|
|
|
|
//%spawnPoint = $AIspawn::SpawnPoint[%index];
|
|
|
|
if ($DebugMode) echo("spawnTownbot(" @ %pos @ ", " @ %team @ ", " @ %type @ ", " @ %race @ ", " @ %shop @ ", " @ %name @ ")");
|
|
|
|
if (!(%type $= "Merchant" || %type $= "Bank" || %type $= "Guild" || %type $= "Porter" || %type $= "Boat"))
|
|
return false;
|
|
|
|
%armor = %race @ "Armor";
|
|
// console spam fix
|
|
switch$(%armor)
|
|
{
|
|
case "MaleOrcArmor": %doyouwantamedalorsomething = true;//echo("valid");
|
|
case "MaleHumanArmor": %doyouwantamedalorsomething = true;//echo("valid");
|
|
case "GoblinArmor":%armor = "MaleOrcArmor";
|
|
default:%armor = "MaleHumanArmor";
|
|
}
|
|
%player = new Player()
|
|
{
|
|
dataBlock = %armor;
|
|
};
|
|
$townbotlist = %player SPC $townbotlist;
|
|
%player.setTransform(%pos);
|
|
MissionCleanup.add(%player);
|
|
%player.name = %name;
|
|
%player.namebase = %name;
|
|
%player.istownbot = true;
|
|
%player.team = %team;
|
|
%player.mtype = %type;
|
|
%player.shop = %shop;
|
|
if(%type $= "Merchant")
|
|
{
|
|
%player.shopwloadout = $shop::loadoutweapons[%shop];
|
|
%player.shopaloadout = $shop::loadoutarmors[%shop];
|
|
%player.shopiloadout = $shop::loadoutItems[%shop];
|
|
}
|
|
return %player;
|
|
}
|
|
|
|
//*********
|
|
datablock ParticleData(AISpawnGlobeSmoke) {
|
|
dragCoeffiecient = 0.0;
|
|
gravityCoefficient = -0.5; // rises slowly
|
|
inheritedVelFactor = 0.0;
|
|
windCoefficient = 0.0;
|
|
|
|
lifetimeMS = 1000; // lasts 2 second
|
|
lifetimeVarianceMS = 0; // ...more or less
|
|
|
|
textureName = "special/BlueImpact";
|
|
|
|
//useInvAlpha = true;
|
|
spinRandomMin = -300.0;
|
|
spinRandomMax = 300.0;
|
|
|
|
constantAcceleration = 0;
|
|
|
|
colors[0] = "0.7 0.5 1.0 0.0";
|
|
colors[1] = "0.7 0.5 1.0 0.2";
|
|
colors[2] = "0.7 0.5 1.0 0.2";
|
|
colors[3] = "0.7 0.5 1.0 0.0";
|
|
|
|
sizes[0] = 0.6;
|
|
sizes[1] = 0.5;
|
|
sizes[2] = 0.4;
|
|
sizes[3] = 0.2;
|
|
|
|
times[0] = 0.0;
|
|
times[1] = 0.33;
|
|
times[2] = 0.9;
|
|
times[3] = 1.0;
|
|
};
|
|
|
|
datablock ParticleEmitterData(AISpawnGlobeEmitter) {
|
|
ejectionPeriodMS = 0.1;
|
|
periodVarianceMS = 0;
|
|
ejectionVelocity = 0.0;
|
|
velocityVariance = 0.0;
|
|
ejectionOffset = 2;
|
|
thetaMin = 0;
|
|
thetaMax = 180;
|
|
overrideAdvances = false;
|
|
particles = "AISpawnGlobeSmoke";
|
|
};
|
|
|
|
function BotSpawnEffects(%player) {
|
|
%position = %player.getWorldBoxCenter();
|
|
|
|
//%c = containerRayCast(%opos, vectorAdd(%opos, "0 0 -100"), $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType, 0);
|
|
|
|
//%position = vectorAdd(posFromRaycast(%c), "0 0 1");
|
|
//******************************
|
|
%sound = LightningHitSound; //change if you want to.
|
|
Serverplay3D(%sound, %position);
|
|
//******************************
|
|
%spawnEMIT = new ParticleEmissionDummy() {
|
|
position = %position;
|
|
rotation = "1 0 0 1";
|
|
scale = "1 1 1";
|
|
dataBlock = defaultEmissionDummy;
|
|
emitter = AISpawnGlobeEmitter;
|
|
velocity = "1";
|
|
};
|
|
MissionCleanup.add(%spawnEMIT);
|
|
%spawnEMIT.schedule(1000, "Delete");
|
|
}
|