Re: RocketX-9 (WIP)
Posted: Mon Apr 20, 2020 8:54 pm
I have a new build for RX9 coming soon. Just working on the afterburner meshes and cleaning up the aircraft self intersecting faces. I'm estimating Thursday for testing.
An Unreal Tournament Community
http://hofgamingclan.site.nfoservers.com/forums/
http://hofgamingclan.site.nfoservers.com/forums/viewtopic.php?t=445
Plain UT 436/440. Paths are working. Pawn attempts the shortest route to you, here also it depends on where is your location. They can use ground paths or fly paths. Monster capable to fly actually can go where wants, if this pawn can swim, technically nothing stops it to track paths unless a small spot blocks it.
Code: Select all
//=====================================================================
// RX9_01.
// ""(§)FrÅgÊd(§)""
// **Monarch**
//
// 555 ---===CrAzYBoNeS===--- 555
// Boppolis_The_Dog
//
//
// Thank you Al McElrath for SLV2.
//=====================================================================
/** Nav point in the sky.
*/
class SkyNode extends NavigationPoint;
// DATA
//
var() float linkRadius;
var() float randomLinkAdjust;
var() float suggestedSpeed;
var() bool bOffensiveNode;
// Used in racing.
var() bool bGateNode;
var() bool bFinalNode;
var SkyNode links[5];
var float ldists[5];
var SkyNodeBeam beams[5];
var float weight[16];
var bool bWeighed;
var int weighDepth;
/** Keep track of launches so we can decide whether or not to try on
this one again. We keep the same launch data for both teams. It's an
anti-stupidity thing. Same for wall deathes, but not shots.
*/
var int launches;
var int launchSxs;
var int passes; // No. of times somebody's passed us.
var int teamPasses[4]; // Same as above, but for teams.
var int wallDeaths; // Times we've ran into a wall on this node.
var int shotDeaths[4]; // Times we've been shot down, per team.
var SkyNode nextSkyNode;
var SkyNode prevSkyNode;
var NavigationPoint navPoint;
// Track nodes we're welding to us, to avg. our position.
var vector weldLoc;
var int weldSum;
var Util u;
// METHODS
//
function postBeginPlay() {
u = spawn(Class'Util', self);
}
function float getWeight(byte team) {
return weight[team];
}
function weld(vector l) {
weldSum++;
weldLoc += l;
}
function setWeldLoc() {
if (weldSum > 0) {
setLocation((location + weldLoc) / (weldSum + 1.0));
}
}
/** Gets called by the launcher at launch. If they reached their
second node, they call us a success.
*/
function addLaunch(optional bool bSuccess) {
if (bSuccess)
launchSxs++;
else
launches++;
}
/** Returns the perc. of launch successes with this node. We give
the node the benefit of the doubt if it hasn't been used yet.
*/
function float launchWeight() {
return ((launchSxs + 1) / float(launches + 1));
}
function SkyNode randomLink() {
local int i;
i = rand(arrayCount(links));
// The links may be none, but they're sorted.
while (links[i] == none && i > 0)
i--;
u.debug("randomLink(): " $ u.sname(links[i]), DL_Verbose);
return links[i];
}
/** Returns true on success. False if no links were created.
*/
function bool linkUp(float r) {
local SkyNode sn;
local int i;
local float dist;
local bool bNone;
bNone = true;
// Use mine if it's set.
if (linkRadius > 0)
r = linkRadius;
foreach radiusActors(Class'SkyNode', sn, r) {
if (sn != self && fastTrace(sn.location, location)) {
dist = vsize(location - sn.location);
bNone = false;
for (i = 0; i < arrayCount(links); i++) {
if (dist < ldists[i] || ldists[i] == 0) {
insertLink(i, sn, dist);
break;
}
}
}
}
return !bNone;
}
/** Used for debugging.
*/
function showBeams(int goal) {
local int i;
local SkyNodeBeam beam;
local float w, hi, lo;
for (i = 0; i < arrayCount(links); i++) {
if (beams[i] == none) {
w = links[i].weight[goal];
if (i == 0) {
hi = w;
lo = w;
} else if (w < lo) {
lo = w;
} else if (w > hi) {
hi = w;
}
beams[i] = spawn(Class'SkyNodeBeam',,,location, rotator(links[i].location - location));
beams[i].drawScale = ldists[i] / 100.0;
}
}
for (i = 0; i < arrayCount(links); i++) {
if (beams[i] != none) {
beams[i].ambientGlow = 255 * ((links[i].weight[goal] - lo) / (hi - lo));
beams[i].scaleGlow = beams[i].ambientGlow;
beams[i].lightBrightness = beams[i].ambientGlow;
}
}
}
/** Used for debugging.
*/
function hideBeams() {
local int i;
for (i = 0; i < arrayCount(links); i++) {
if (beams[i] != none)
beams[i].destroy();
}
}
function insertLink(int index, SkyNode n, float dist) {
local int i;
for (i = arrayCount(links) - 2; i >= index; i--) {
if (links[i] != none) {
links[i + 1] = links[i];
ldists[i + 1] = ldists[i];
}
}
links[index] = n;
ldists[index] = dist;
}
function vis(bool on, optional int goal) {
if (!on)
hideBeams();
else
showBeams(goal);
}
function destroyed() {
u.debug("destroyed()", DL_Verbose);
if (prevSkyNode != none)
prevSkyNode.nextSkyNode = nextSkyNode;
}
// end
defaultproperties
{
suggestedSpeed=-1.000000
bStatic=False
Style=STY_Translucent
Texture=Texture'SLV2Textures.muzf.Spark'
bCollideActors=True
}]
Code: Select all
//=====================================================================
// RX9_01.
// ""(§)FrÅgÊd(§)""
// **Monarch**
//
// 555 ---===CrAzYBoNeS===--- 555
// Boppolis_The_Dog
//
//
// Thank you Al McElrath for SLV2.
//=====================================================================
/** SkyNet. Spawned on the server to build the sky node network. Built
slowly over time in latent code so we don't choke.
*/
class SkyNet extends SLInfo config (RX9_01);
// DATA
//
// When we started.
var float buildStamp;
// Set based on gametype in postBeginPlay().
var bool bCTF, bAss;
// Tag given to auto-spawned nodes.
var() name autotag;
// Used during auto-spawning.
var NavigationPoint autonp;
var SkyNode firstsn, autosn;
var int i;
/** Map type. 0 == no sky nodes. 1 == tagged path nodes. 2 == sky
nodes.
*/
var int type;
var byte goalnum;
var Actor goals[16];
var SkyNode goalNodes[16];
var float maxGoalDist[16];
var int nodeSum;
var() float weldRadius;
var() float linkRadius;
// The angle between a launch node and the next one that is "launchable". See goodNode().
var() float goodAngle;
// Set when we've finished building.
var bool bBuilt;
// For visual debugging.
var() config bool bShowNodes;
var() config bool bShowLinks;
// So we can do debugging just for the sky net.
var() config bool bDebug;
var() bool bNoAutoWeightNodes;
var() float randomLinkAdjust;
var() int laps;
var Util u;
// METHODS
//
function postBeginPlay() {
u = spawn(Class'Util', self);
u.setDebugLevel(DL_Verbose);
if (bDebug)
u.setOutputLevel(DL_Verbose);
if (!properGame()) {
u.err("postBeginPlay(): Only usable in CTF or Assault. Destroying.");
destroy();
}
if (bAss)
// 16 possible fort standards.
goalnum = Assault(level.game).numForts;
else
// Only 4 flags.
goalnum = 4;
setMapType();
u.debug("postBeginPlay(): map type: " $ type);
}
function setMapType() {
local SkyNode sn;
local NavigationPoint np;
foreach allActors(Class'SkyNode', sn) {
type = 3;
return;
}
foreach allActors(Class'NavigationPoint', np, 'SKYNODE') {
type = 2;
return;
}
// No SL support.
type = 1;
}
/** Currently only works with CTF and Assault.
*/
function bool properGame() {
if (level.game.isA('CTFGame'))
bCTF = true;
if (level.game.isA('Assault'))
bAss = true;
return (bCTF || bAss);
}
/** Pick a random goal. The Optional args are for excluding a specific
goal. Not currently used.
*/
function byte randomGoal(optional bool bEx, optional byte exgoal) {
local int i, pnum;
local int poss[16];
for (i = 0; i < goalnum; i++) {
if (goals[i] != none && !(bEx && i == exgoal)) {
poss[pnum] = i;
pnum++;
}
}
if (pnum > 0) {
return poss[rand(pnum)];
} else {
u.err("randomGoal(): no possible goals!");
return 0;
}
}
/** Returns the first node near us that has a positive launch record.
*/
function SkyNode findLaunchNode(Bot b) {
local int team;
local SkyNode sn, ln;
local byte goal;
local float cw, w;
// Init.
goal = -1;
// If we are close to where we want to be, don't launch!
if (getGoal(b, goal)) {
if (vsize(goalNodes[goal].location - b.location) < linkRadius * 2.0) {
u.debug("findLaunchNode(): in range of goal");
return none;
}
}
// Find the heaviest, good node.
foreach b.radiusActors(Class'SkyNode', sn, linkRadius) {
if (sn.launchWeight() > 0.50) {
// Don't use this one if we'll have to do a 180 once we reach it.
if (goodNode(sn, b)) {
if (goal == -1) {
// No goal? Just use the first one.
ln = sn;
break;
} else {
cw = sn.getWeight(goal);
if (ln == none) {
ln = sn;
w = cw;
} else {
if (cw > w) {
ln = sn;
w = cw;
}
}
}
}
}
}
if (ln != none) {
u.debug("findLaunchNode(): node: " $ u.sname(ln));
return ln;
} else {
u.debug("findLaunchNode(): no good nodes");
return none;
}
}
/** This sets the goal index. We may set bEject, so this needs to
happen just before we test for that in pilotBehavior(). Returns
true if we have a valid goal.
*/
function bool getGoal(Bot bot, out byte goal) {
local byte team;
local FortStandard fort;
local int i;
team = bot.playerReplicationInfo.team;
// Set our goal!
if (bCTF) {
// Are we carrying a flag?
if (bot.playerReplicationInfo.hasFlag != none) {
goal = team;
} else {
// Go for an enemy flag!
//goal = randomGoal(true, team);
goal = findEnemyFlagGoal(team);
}
} else if (bAss) {
fort = Assault(level.game).bestFort;
if (fort != none) {
if (FortStandard(goals[goal]) != fort) {
// Find the new fort index.
for (i = 0; i < goalnum; i++) {
if (goals[i] == fort) {
goal = i;
break;
}
}
}
} else {
u.err("setGoal(): No best fort. Ejecting.");
return false;
}
}
return true;
}
/** FIX this.
*/
function byte findEnemyFlagGoal(byte team) {
local int i;
for (i = 0; i < goalnum; i++) {
if (i != team) { // && flagAtBase(i)) {
return i;
}
}
}
/** Returns true if the flag is safe and sound.
*/
function bool flagAtBase(byte team) {
return CTFReplicationInfo(level.game.gameReplicationInfo).flagList[team].bHome;
}
/** Return true if there is a node after n which is roughly in a
continuous direction from the bot and not blocked.
*/
function bool goodNode(SkyNode n, Bot b) {
local vector ton;
if (n != none) {
u.debug("goodNode(" $ u.sname(n) $ ", " $ u.sname(b) $ ")");
ton = normal(n.location - b.location);
for (i = 0; i < arrayCount(n.links); i++) {
if (n.links[i] != none && fastTrace(n.links[i].location, n.location) && (ton dot normal(n.location - n.links[i].location)) > goodAngle) {
return true;
}
}
}
return false;
}
function SkyNode closestNode(vector loc, float radius) {
local SkyNode sn, closest;
local float dist;
foreach radiusActors(Class'SkyNode', sn, radius, loc) {
if (closest == none || vsize(sn.location - closest.location) < dist)
closest = sn;
}
return closest;
}
/** Build our sky network.
*/
auto state BuildSkyNet {
begin:
u.debug("BuildSkyNet:begin: Building sky network.", DL_Normal);
buildStamp = level.timeseconds;
// Need to auto-spawn sky nodes?
if (type == 1 || type == 2) {
u.debug("BuildSkyNet:begin: Auto-spawning nodes.", DL_Normal);
autonp = level.navigationPointList;
while (autonp != none) {
// Catch our CTF goals here.
if (bCTF && autonp.isA('FlagBase'))
goals[FlagBase(autonp).team] = autonp;
// If type 2, only spawn nodes for tagged path nodes.
if (type == 1 || (type == 2 && autosn.tag == 'SKYNODE')) {
autosn = autoSkyNode(autonp, autosn);
nodeSum++;
}
autonp = autonp.nextNavigationPoint;
sleep(0.0);
}
// Keep track of the last (which will be first).
firstsn = autosn;
u.debug("BuildSkyNet:begin: firstsn: " $ u.sname(firstsn));
u.debug("BuildSkyNet:begin: Rising sky nodes.", DL_Normal);
autosn = firstsn;
while (autosn != none) {
autosn.setWeldLoc();
riseSkyNode(autosn);
autosn = autosn.nextSkyNode;
sleep(0.0);
}
}
// Assault goals done separately here. Copy them over.
if (bAss) {
for (i = 0; i < goalnum; i++) {
goals[i] = Assault(level.game).fort[i];
}
}
linkNodes:
u.debug("BuildSkyNet:linkNodes: Linking sky nodes.", DL_Normal);
autosn = firstsn;
while (autosn != none) {
// Destroy it if it has no links.
if (!autosn.linkUp(linkRadius)) {
// Need to keep a first one.
if (autosn == firstsn)
firstsn = autosn.nextSkyNode;
autosn.destroy();
}
autosn = autosn.nextSkyNode;
sleep(0.0);
}
weightNodes:
// Weigh the links, depending on gametype.
if (!bNoAutoWeightNodes) {
u.debug("BuildSkyNet:weightNodes: Weighting sky nodes.", DL_Normal);
// Assign goal nodes.
for (i = 0; i < goalnum; i++) {
if (goals[i] != none)
goalNodes[i] = closestNode(goals[i].location, linkRadius);
u.debug("BuildSkyNet:weightNodes: new goal node: " $ u.sname(goalNodes[i]) $ " for: " $ u.sname(goals[i]));
}
// Set the weight to the distance first.
autosn = firstsn;
while (autosn != none) {
for (i = 0; i < goalnum; i++) {
if (goalNodes[i] != none) {
autosn.weight[i] = vsize(goalNodes[i].location - autosn.location);
u.debug("BuildSkyNet:weightNodes: " $ u.sname(autosn) $ ": distance to goal node " $ i $ ": " $ autosn.weight[i]);
if (autosn.weight[i] > maxGoalDist[i])
maxGoalDist[i] = autosn.weight[i];
}
}
sleep(0.0);
autosn = autosn.nextSkyNode;
}
// Now divide by the max and subtract from 1.0 to get the weight.
u.debug("BuildSkyNet:weightNodes: dividing distances: firstsn: " $ u.sname(firstsn));
autosn = firstsn;
while (autosn != none) {
for (i = 0; i < goalnum; i++) {
if (goalNodes[i] != none) {
autosn.weight[i] = 1.0 - (autosn.weight[i] / maxGoalDist[i]);
u.debug("BuildSkyNet:weightNodes: " $ u.sname(autosn) $ ": goal: " $ i $ " weight: " $ autosn.weight[i]);
}
}
sleep(0.0);
autosn = autosn.nextSkyNode;
}
}
// End.
u.debug("BuildSkyNet:begin: Built network in " $ u.sf(level.timeseconds - buildStamp) $ " seconds.", DL_Normal);
bBuilt = true;
} // End BuildSkyNet.
function SkyNode autoSkyNode(NavigationPoint np, SkyNode lastsn) {
local SkyNode n;
// Don't weld goal nodes.
if (!isGoalNavPoint(np)) {
foreach np.radiusActors(Class'SkyNode', n, weldRadius) {
u.debug("autoSkyNode(): welded " $ u.sname(np) $ " to " $ u.sname(n));
n.weld(np.location);
// Return the last one, for setting firstsn.
return lastsn;
}
}
n = spawn(Class'SkyNode',, 'AutoSkyNode', np.location);
if (n == none) {
u.err("autoSkyNode(): spawn failed for " $ u.sname(np));
return lastsn;
}
if (bShowNodes)
n.bHidden = false;
n.navPoint = np;
n.nextSkyNode = lastsn;
if (lastsn != none)
lastsn.prevSkyNode = n;
u.debug("autoSkyNode(): new skynode for " $ u.sname(np));
return n;
}
function bool isGoalNavPoint(NavigationPoint np) {
return ((bASS && np.isA('FortStandard')) || (bCTF && np.isA('FlagBase')));
}
function linkNodes() {
local SkyNode last, n;
foreach allActors(Class'SkyNode', n) {
n.nextSkyNode = last;
last = n;
}
}
function riseSkyNode(SkyNode n) {
local vector down, up;
// Don't rise goal nodes.
if (!isGoalNavPoint(n.navPoint)) {
down = roof(n.navPoint, -500);
up = roof(n.navPoint, 500);
n.setLocation(down + (up - down) * 0.5);
}
}
function vector roof(Actor a, float dist) {
local Actor hit;
local vector end, hl, hn;
end = a.location + vect(0, 0, 1) * dist;
hit = a.trace(hl, hn, end, a.location, false);
if (hit != none)
return hl;
else
return end;
}
// end
defaultproperties
{
autotag=autoSkyNode
weldRadius=300.000000
linkRadius=1800.000000
goodAngle=0.200000
randomLinkAdjust=0.050000
}
Code: Select all
ReadyToAttack:
DesiredRotation = Rotator(Target.Location - Location);
PlayRangedAttack();
if ( Weapon.bMeleeWeapon )
GotoState('Attacking');
Enable('AnimEnd');
Firing: //Firing here
if ( Target == None )
GotoState('Attacking');
TurnToward(Target);
Goto('Firing'); //GoTo Firing if target still there - target might don't do anything - like I did and it will exist and DispersionPistol exists - Jessus
Code: Select all
ReadyToAttack:
DesiredRotation = Rotator(Target.Location - Location);
PlayRangedAttack();
Enable('AnimEnd');
Firing:
if ( Target == None )
GotoState('Attacking');
TurnToward(Target);
Goto('Firing');
Code: Select all
class Konglauncher extends SLWeapon config (....
....
event float BotDesireability(Pawn Bot)
{
local float desire;
local bool bHaveJet;
local Inventory Inv;
for ( Inv=Bot.Inventory; Inv!=None; Inv=Inv.Inventory )
{
if ( Inv.IsA('Konglauncher') )
{
bHaveJet = True;
if ( KongLauncher(Inv).AmmoType == None || (KongLauncher(Inv).AmmoType.AmmoAmount < 1 && !KongLauncher(Inv).bWeaponStay) )
return 3;
return -1;
}
}
if ( !bHaveJet )
return 3;
else
return -1;
return Super.BotDesireability(Bot);
}
Code: Select all
//Get framerate level: 0 = OK, -1=>-5 = Slowdown, 1=>5+ = Speedup
simulated static function int getFrameRateLevel(LevelInfo Lvl, float Delta, optional bool returnExcessLevel)
{
local float frameRate, minFPS;
if (!Class'NWInfo'.default.enableGlobalSmartPerformance)
return 0;
frameRate = 1/(Delta * Lvl.TimeDilation);
minFPS = Class'NWInfo'.default.smartPerformanceMinFPS;
if (!returnExcessLevel && frameRate >= minFPS)
return 0;
return Int(frameRate / (minFPS / 5.0)) - 5;
}
//Get LODBias value based on current framerate
simulated static function float getFrameRateBasedLODBias(LevelInfo Lvl, float Delta, float curLODBias)
{
local int perfoEval;
perfoEval = static.getFrameRateLevel(Lvl, Delta, True);
if (perfoEval == 1)
return curLODBias;
return FClamp(curLODBias + static.getSign(perfoEval)*Delta*3, Class'NWInfo'.default.MinLODBias, Class'NWInfo'.default.MaxLODBias);
}