Compare commits

...

4 commits
v0.6 ... main

8 changed files with 372 additions and 70 deletions

1
.gitignore vendored
View file

@ -8,6 +8,7 @@ lighting/
prefs/
gui/
recordings/
fonts/
Classic*
# scripts folder need to be ignored and then exclusions have to be carved out

View file

@ -4,49 +4,20 @@ SkillSector is a game mode for Tribes 2 for building skills you will need to pla
# Mode plan
Building on the concepts seen in the [Training Grounds](https://github.com/jakraska/Tribes-2-Training-Grounds/) game mode by [jakraska](https://github.com/jakraska), SkillSector hopes to achieve the following features for the following modes.\
#### Movement and shooting
- [ ] Flying aim training, multiple difficulty levels
#### Aim training
- [x] Static aim training
- [ ] Dynamic aim training
- [ ] LakRabbit aim training
#### Duelling
- [ ] Human duel arena(s)
- [ ] Robot duel arena(s)
#### Flag handling
- [ ] Flag toss practice
- [ ] Baseball machine flag catch practice (CTF, TR2)
- [ ] Human flag practice (CTF, TR2)
- [x] Flag toss practice
- [x] Baseball machine flag catch practice (CTF, TR2)
- [x] Human flag practice (CTF, TR2)
#### Toys
- [ ] Grav cycle racing
- [ ] Ski racing
# Modes
## Flying aim training
### Beginner difficulty
Static targets. Shots will only count when the player is...
- In the air
- Travelling at a minimum velocity
Different weapons will have different scores based on their 'ease' of hitting a static target.\
Static targets will be both on the ground and in the air.\
Hitting a static target with splash damage will count, but won't grant much score compared to a direct hit.
### Moderate difficulty
Moving targets. Splash damage does not count. Same rules as previous.
### Advanced difficulty
Fast moving targets. Same rules as previous.
## Human duel arena(s)
Humans should be able to schedule a duel between themselves. I like the way that TG did it.
## Robot duel arena(s)
Humans should be able to select from various difficulty robots for dueling.
## Flag toss/catch practice
Flag tossing and flag catching require a fair bit of practice. Doing so manually or between players
#### auxiliary todo list / odds and ends
- noIndividualDamage could be set for the roof's power stations, making it possible to annoy other players by disabling FloatingBank's inventory station(s)
# map ideas
# twin towers 9/11 map is a good meme
# flying aim training thinking

View file

@ -13,11 +13,11 @@
//--- OBJECT WRITE BEGIN ---
new SimGroup(MissionGroup) {
musicTrack = "ice";
cdTrack = "5";
powerCount = "0";
Hunters_timeLimit = "25";
Team_Hunters_timeLimit = "25";
musicTrack = "ice";
new MissionArea(MissionArea) {
area = "-1008 -1032 2144 2080";
@ -63,14 +63,14 @@ new SimGroup(MissionGroup) {
cullDensity = "0.3";
customArea = "0 0 0 0";
GraphFile = "Scarabrae_nef.nav";
position = "0 0 0 1";
coverage = "0";
conjoinBowlDev = "20";
rotation = "0 0 0 0";
coverage = "0";
scale = "1 1 1";
XDimOverSize = "0";
YDimOverSize = "0";
scale = "1 1 1";
conjoinBowlDev = "20";
GraphFile = "Scarabrae_nef.nav";
locked = "true";
};
new Sky(Sky) {
@ -267,7 +267,7 @@ new SimGroup(MissionGroup) {
homingCount = "0";
team = "0";
Trigger = "4552";
Trigger = "34762";
Target = "34";
locked = "false";
};
@ -280,7 +280,7 @@ new SimGroup(MissionGroup) {
homingCount = "0";
team = "0";
Trigger = "4554";
Trigger = "34764";
Target = "35";
locked = "false";
};
@ -303,7 +303,7 @@ new SimGroup(MissionGroup) {
homingCount = "0";
team = "0";
Trigger = "4557";
Trigger = "34767";
Target = "36";
locked = "false";
};
@ -400,10 +400,10 @@ new SimGroup(MissionGroup) {
lockCount = "0";
homingCount = "0";
Trigger = "4568";
Target = "39";
inUse = "Down";
notReady = "1";
Trigger = "34778";
inUse = "Down";
Target = "39";
};
new Marker(BankSpawn) {
position = "-155.307 126.636 243.233";
@ -425,9 +425,9 @@ new SimGroup(MissionGroup) {
homingCount = "0";
Desc = "Dynamic Aim Trainer\nShoot moving targets while in the air to score points!\nMove faster to score more points and have fun!";
Target = "40";
wrangle = "Aim Trainer teleports";
destination = "ATMSpawn";
Target = "40";
};
new StaticShape(ATHT) {
position = "-170.634 150.644 233.142";
@ -438,8 +438,8 @@ new SimGroup(MissionGroup) {
homingCount = "0";
Desc = "Aim Trainer\nShoot fast moving targets while in the air to score points!\nMove faster to score more points and have fun!";
Target = "41";
destination = "ATHSpawn";
Target = "41";
};
new StaticShape(ATLT) {
position = "-176.634 144.844 233.142";
@ -450,8 +450,34 @@ new SimGroup(MissionGroup) {
homingCount = "0";
Desc = "Static Aim Trainer\nShoot static targets while in the air to score points!\nMove faster to score more points and have fun!";
Target = "42";
destination = "ATLSpawn";
Target = "42";
};
new StaticShape(DuelZone) {
position = "-140.434 150.844 233.142";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "BankTeleporter";
lockCount = "0";
homingCount = "0";
Desc = "it\'s time to d-d-d-d-d-d-d-duel";
wrangle = "Duel zone teleports";
destination = "undefined";
Target = "43";
};
new StaticShape(FTT) {
position = "-176.634 117.644 233.142";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "BankTeleporter";
lockCount = "0";
homingCount = "0";
Desc = "Flag Training Zone\nCatch flags! Throw flags!\nWe love flags!";
wrangle = "Flag Trainer teleport";
destination = "FTSpawn";
Target = "44";
};
};
new ForceFieldBare(TractorBeamFront) {
@ -463,9 +489,9 @@ new SimGroup(MissionGroup) {
homingCount = "0";
gravityMod = "-2.75";
originalscale = "10 40 140";
appliedForce = "0 0 0";
pz = "4575";
originalscale = "10 40 140";
pz = "34787";
Target = "-1";
velocityMod = "1.0";
};
@ -480,6 +506,16 @@ new SimGroup(MissionGroup) {
Target = "45";
};
new WayPoint() {
position = "-158.549 134.258 252.611";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "WayPointMarker";
lockCount = "0";
homingCount = "0";
name = "The Bank";
team = "0";
};
};
new SimGroup(AimTrain) {
@ -542,8 +578,8 @@ new SimGroup(MissionGroup) {
homingCount = "0";
Desc = "\nWelcome back to the Bank!";
Target = "43";
destination = "BankSpawn";
Target = "45";
};
new Marker(ATLSpawn) {
position = "-546.054 112.086 223.904";
@ -558,23 +594,55 @@ new SimGroup(MissionGroup) {
powerCount = "0";
new Marker(ATMSpawn) {
position = "-203.46 693.682 274.118";
rotation = "0 0 -1 90";
position = "-283.86 678.282 266.518";
rotation = "1 0 0 0";
scale = "1 1 1";
seqNum = "0";
msToNext = "1000";
};
new StaticShape(ATMBankTeleport) {
position = "-197.111 696.524 262.891";
rotation = "1 0 0 0";
position = "-284.511 664.298 254.306";
rotation = "-1 0 0 12";
scale = "1 1 1";
dataBlock = "BankTeleporter";
lockCount = "0";
homingCount = "0";
Desc = "\nWelcome back to the Bank!";
Target = "44";
destination = "BankSpawn";
Target = "46";
};
new TSStatic(LeftPlaceholder) {
position = "-419.363 775.104 251.039";
rotation = "0 0 1 180";
scale = "1 1 1";
shapeName = "statue_hmale.dts";
placeholder = "1";
};
new TSStatic(MidPlaceholder) {
position = "-340.323 809.004 247.674";
rotation = "0 0 -1 90";
scale = "1 1 1";
shapeName = "statue_lfemale.dts";
placeholder = "1";
};
new TSStatic(RightPlaceholder) {
position = "-229.983 815.217 248.474";
rotation = "0 0 1 180";
scale = "1 1 1";
shapeName = "statue_lfemale.dts";
placeholder = "1";
};
new TSStatic(JetPlaceholder) {
position = "-210.451 631.718 267.535";
rotation = "0 0 1 180";
scale = "1 1 1";
shapeName = "statue_lfemale.dts";
placeholder = "1";
};
};
new SimGroup(AimTrainHigh) {
@ -582,5 +650,93 @@ new SimGroup(MissionGroup) {
powerCount = "0";
};
};
new SimGroup(FlagTrain) {
powerCount = "0";
new Marker(FTSpawn) {
position = "284.013 -543.625 261.344";
rotation = "0 0 -1 90";
scale = "1 1 1";
seqNum = "0";
msToNext = "1000";
};
new StaticShape(FTBankTeleport) {
position = "272.726 -537.15 254.086";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "BankTeleporter";
lockCount = "0";
homingCount = "0";
Desc = "\nWelcome back to the Bank!";
destination = "BankSpawn";
Target = "47";
};
new StaticShape() {
position = "264.386 -581.653 232.142";
rotation = "-1 0 0 15";
scale = "1 1 1";
dataBlock = "ExteriorFlagStand";
lockCount = "0";
homingCount = "0";
Target = "-1";
};
new StaticShape() {
position = "247.87 -543.343 249.677";
rotation = "0 1 0 15";
scale = "1 1 1";
dataBlock = "ExteriorFlagStand";
lockCount = "0";
homingCount = "0";
Target = "-1";
};
new StaticShape() {
position = "319.348 -598.244 226.873";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "ExteriorFlagStand";
lockCount = "0";
homingCount = "0";
Target = "-1";
};
new StaticShape() {
position = "164.875 -615.487 223.553";
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "ExteriorFlagStand";
lockCount = "0";
homingCount = "0";
Target = "-1";
};
new StaticShape() {
position = "264.341 -564.157 241.442";
rotation = "-1 0 0 40";
scale = "1 1 1";
dataBlock = "ExteriorFlagStand";
lockCount = "0";
homingCount = "0";
flagvel = "0 -25 40";
cannon = "1";
Target = "-1";
};
new StaticShape() {
position = "310.537 -493.475 229.386";
rotation = "0.67341 0 0.739269 100";
scale = "1 1 1";
dataBlock = "ExteriorFlagStand";
lockCount = "0";
homingCount = "0";
flagvel = "15 30 40";
cannon = "1";
Target = "-1";
};
};
};
//--- OBJECT WRITE END ---

View file

@ -85,7 +85,7 @@ function DermDummy::damageObject(%data, %targetObject, %sourceObject, %position,
// echo("wtf is this then: " @ %this @ " tgt " @ %sourceObject);
// }
function AimTrainerInit() {
function InitAimTrainer() {
if (!$DEVMODE) {
findAndReplacePlaceholders();
}

View file

@ -0,0 +1,144 @@
// TODO: flag goals
// Time in seconds
$FlagTrainerTossReset = 45;
$FlagTrainerGrabReset = 90;
$FlagTrainerCannonInterval = 25;
function Flag::objectiveInit(%data, %flag) {
%flag.originalPosition = %flag.getTransform();
$flagPos[%flag.team] = %flag.originalPosition;
%flag.isHome = true;
%flag.carrier = 0;
%flag.grabber = 0;
}
function SkillSectorGame::flagStandCollision(%game, %dataBlock, %obj, %colObj) {
if (%colObj.getDatablock().getName() $= "FLAG" && !%colObj.isHome) {
returnFlag(%colObj, 'StandCollide');
}
}
function initFlagStand(%stand) {
// Give the stand a flag
echo("Found a stand");
%flag = new Item() {
position = %stand.getPosition();
className = FlagObj;
dataBlock = "FLAG";
static = false;
rotate = true;
};
FlagTrain.add(%flag);
%stand.flag = %flag;
%flag.stand = %stand;
if(%flag.stand) {
%flag.stand.getDataBlock().onFlagReturn(%flag.stand);
}
if (%stand.cannon) {
// Stand is a flag cannon! Fire the missiles!
$Cannons[$CannonCount] = %stand;
$CannonCount++;
flagCannon(%stand);
}
}
function flagCannon(%stand) {
// Fire flag and schedule another flag fire
%flag = %stand.flag;
if (isObject(%flag)) {
%flag.setVelocity(%stand.flagvel);
cancel(%stand.cannonSched); // don't allow accidental re-queue
%stand.cannonSched = schedule($FlagTrainerCannonInterval*1000, 0, flagCannon, %stand);
returnFlagAfter(%flag, $FlagTrainerCannonInterval-2, 'CannonReset');
}
}
function scanGroupForFlagStands(%group) {
for (%i = 0; %i < %group.getCount(); %i++) {
%obj = %group.getObject(%i);
if (%obj.getClassName() $= "SimGroup") {
scanGroupForFlagStands(%obj);
} else if (%obj.getClassName() $= "StaticShape" && %obj.getDatablock().getName() $= "ExteriorFlagStand") {
initFlagStand(%obj);
}
}
}
function SkillSectorGame::InitFlagTrainer() {
if ($DEVMODE) {
// echo("Not putting a flags on stands");
return;
}
$CannonCount = 0;
// Find all the flag stands and give them a flag
scanGroupForFlagStands(FlagTrain);
}
function SkillSectorGame::ShutdownFlagTrainer() {
for (%i = 0; %i < $CannonCount; %i++) {
cancel($Cannons[%i].cannonSched);
}
}
function SkillSectorGame::playerTouchFlag(%game, %player, %flag) {
if (isObject(%player.holdingFlag)) {
messageClient(%player.client, 'MsgFlagAlready', '\c0You\'re already holding a flag - don\'t be greedy!');
return;
}
if (isObject(%flag.carrier)) {
echo("Can't pick up a flag that's being carried");
return;
}
%game.playerTouchEnemyFlag(%player, %flag);
}
function SkillSectorGame::playerTouchEnemyFlag(%game, %player, %flag) {
%client = %player.client;
%player.holdingFlag = %flag;
%flag.carrier = %player;
%player.mountImage(FlagImage, $FlagSlot, true, 'dsword');
%flag.hide(true);
%flag.startFade(0, 0, false);
if(%flag.stand) %flag.stand.getDataBlock().onFlagTaken(%flag.stand);
returnFlagAfter(%flag, $FlagTrainerGrabReset, 'GrabReset');
}
function SkillSectorGame::dropFlag(%game, %player) {
%player.throwObject(%player.holdingFlag);
}
function returnFlag(%flag, %reason) {
if (isObject(%flag.carrier)) {
%flag.carrier.unMountImage($FlagSlot);
%flag.hide(false);
%flag.carrier.holdingFlag = 0; // tell the player they've lost the flag
}
if(%flag.stand) %flag.stand.getDataBlock().onFlagReturn(%flag.stand);
%flag.setVelocity("0 0 0");
%flag.setTransform(%flag.stand.getTransform());
%flag.isHome = true;
//messageClient(%flag.carrier.client, 'MsgFlagReturned', '\c0Flag returned (%1)', %reason); // Kinda annoying, players will figure this out eventually
%flag.carrier = 0;
}
function returnFlagAfter(%flag, %after, %reason) {
%flag.isHome = false; // happens whenever player tosses or picks up flag. also happens when cannon fires
cancel(%flag.returnSched);
%flag.returnSched = schedule(%after*1000, 0, returnFlag, %flag, %reason);
//messageClient(%flag.carrier.client, 'MsgFlagReturnCountdown', '\c0Flag will be returned to stand in %1 seconds (%2)', %after, %reason); // Kinda annoying, players will figure this out eventually
}
function SkillSectorGame::playerDroppedFlag(%game, %player) {
%client = %player.client;
%flag = %player.holdingFlag;
%player.unMountImage($FlagSlot);
%flag.hide(false);
%flag.setTransform(%flag.getTransform());
returnFlagAfter(%flag, $FlagTrainerTossReset, 'TossReset');
%player.holdingFlag = 0;
%flag.carrier = 0;
}

View file

@ -14,24 +14,31 @@ exec("scripts/SkillSectorTeleporter.cs");
exec("scripts/SkillSectorAimTrainer.cs");
exec("scripts/SkillSectorTractorBeam.cs");
exec("scripts/SkillSectorWaypointWrangler.cs");
exec("scripts/SkillSectorFlagTrainer.cs");
// package SkillSector {
// function none() {}
// package SkillSectorGame {
// function EditorSaveMissionMenu() {
// // Delete all flags, they're spawned at 'boot'
// parent::EditorSaveMissionMenu();
// }
// };
function SkillSectorGame::missionLoadDone(%game)
{
function SkillSectorGame::missionLoadDone(%game) {
DefaultGame::missionLoadDone(%game);
echo("Mission loading...");
AimTrainerInit();
WaypointWranglerInit();
InitAimTrainer();
InitWaypointWrangler();
%game.InitFlagTrainer();
}
function SkillSectorGame::initGameVars(%game)
{
function SkillSectorGame::initGameVars(%game) {
}
function SkillSectorGame::onClientLeaveGame(%client) {
CLWaypointWrangler(%client);
}
// No longer dispatching 'primary' waypoints because they can't be made semi-permanent.
@ -49,6 +56,14 @@ function SkillSectorGame::clientMissionDropReady(%game, %client) {
DefaultGame::clientMissionDropReady(%game, %client);
}
function SkillSectorGame::gameOver(%game) {
DefaultGame::gameOver(%game);
WaypointWranglerShutdown();
%game.ShutdownFlagTrainer();
// deactivatePackage(SkillSectorGame);
}
if ($DEVMODE) {
moveMap.unbind(keyboard, "f5");
moveMap.unbind(keyboard, "f6");

View file

@ -38,7 +38,7 @@ function BankTeleporter::onCollision(%data, %obj, %collider) {
messageClient(%collider.client, 'MsgStationDenied', '\c2Teleporter is recharging please stand by. ~wfx/powered/nexus_deny.wav');
return;
}
messageClient(%collider.client, 'MsgTeleportStart', '\c2Teleporter is calculating transport coherence... ~wfx/misc/nexus_idle.wav');
//messageClient(%collider.client, 'MsgTeleportStart', '\c2Teleporter is calculating transport coherence... ~wfx/misc/nexus_idle.wav');
%collider.setVelocity("0 0 0");
%collider.setMoveState(true);
%collider.startFade(1000, 0, true);

View file

@ -42,6 +42,18 @@ function WaypointWranglerZone::onLeaveTrigger(%this, %trigger, %obj) {
function WaypointWranglerZone::onTickTrigger(%this, %trigger) {
}
function CLWaypointWrangler(%client) {
// cancel any ongoing waypoint wrangler scheduler
cancel(%client.wwsched);
}
function ShutdownWaypointWrangler() {
%count = ClientGroup.getCount();
for (%i = 0; %i < %count; %i++) {
cancel(ClientGroup.getObject(%i).wwsched);
}
}
function scanZoneForWaypoints(%group) {
for (%i = 0; %i < %group.getCount(); %i++) {
%obj = %group.getObject(%i);
@ -83,7 +95,7 @@ function scanGroupForWWZ(%group) {
}
}
function WaypointWranglerInit() {
function InitWaypointWrangler() {
// Reset WPZone system
$WPZNextFree = 0;
$WPZones[0] = 0;
@ -105,9 +117,12 @@ function WWDispatch(%client, %zoneIndex) {
for (%i = 1; %i < $WPZPoints[%zoneIndex, 0]+1; %i++) {
showWaypoint(%client, $WPZPoints[%zoneIndex, %i]);
}
cancel(%client.wwsched); // can't be dispatched for more than one zone at once
%client.wwsched = schedule(1900, 0, WWDispatch, %client, %zoneIndex);
}
// This function is unnecessarily expensive, this lookup could be done by attaching the zone and index to the trigger.
// I'm also too lazy to re-write it now
function WWStartWaypointDispatch(%client, %zone) {
// echo("zone count:" @ $WPZNextFree);
for (%i = 0; %i < $WPZNextFree; %i++) {