Jump to content

Random player position with already existing CC


Grapjas
 Share

Recommended Posts

I'm trying to give players a random position on the map im currently making. I took a look at the rmgen scripts but im a lil lost honestly. 

To be clear, my map already has civic centers placed, aswell as the resources, so these things do not have to be randomized. The only thing i want random is where each player will be put into existing CC, while being adjacent to team members.

If up until this part of what i'm asking is not possible the way i discribe it, is it possible to make a custom rmgen2 script and put the exact coordinates where i want players to have their CC placed?

I think i need some parts of rmgen2/setup.js but im doubtful as to how to approach this.

Link to comment
Share on other sites

Grapjas, that's possible but not too straightforward to implement.

You'll basically need to redefine one of:`placePlayerBase`, `placeCivDefaultStartingEntities` functions or any other function that starts with `placePlayerBase*`.

Edited by badosu
  • Thanks 1
Link to comment
Share on other sites

If you don't need full control:

Just assign a variable to the result of the placer function, usually that's `playerPlacementCircle` for typical maps e.g. nobland, get the playerPositions which is the second return argument, add some randomization to the positions and give it back on `placePlayerBases`, e.g.:
 

let playerPlacements = playerPlacementCircle( // ... or whatever is being used as the player placer function
let [playerIDs, playerPositions] = playerPlacements;

// iterate and modify playerPositions e.g.
playerPlacements = [playerIds, playerPositions.map((pos) => _modify_pos_)];

placePlayerBases({
	"PlayerPlacement": playerPlacements, // give it back to 0ad

The root of the territory is the cc location itself, so you can't do much better than this. That's what will be positioned on what you specify there, you can only change the distribution of entities around it via heavy patching or some other clever way of the functions I mentioned on the previous post.

Edited by badosu
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

19 hours ago, Grapjas said:

The only thing i want random is where each player will be put into existing CC, while being adjacent to team members.

Also, can you describe what you mean here? The player is literally the CC and the entities they start with, I'm not sure what you want.

Link to comment
Share on other sites

4 hours ago, badosu said:

Also, can you describe what you mean here? The player is literally the CC and the entities they start with, I'm not sure what you want.

What im aiming for is: I want fixed starting places on the map, but randomize to which fixed place the player will be assigned to. This way e.g. player 3 wont always end up on position 3, but can be assigned to position 8, or 5,  etc. However the team members need to be adjacent to eachother. Im not sure i can formulate it clearly than this :unsure:

Plan A: I already have 8 CC's on the current map im making where i want them to be. I was looking for a way via js to change ownerships of said CC's randomly on start of the game.

Plan B: Delete current existing CC's, let the gen make bases for players, but at 1 of the 8 coördinates provided in the code (if possible at all).

I'll crack my brain with your code :self_hammer:, ty for help.

Edited by Grapjas
Link to comment
Share on other sites

59 minutes ago, Grapjas said:

I already have 8 CC's on the current map im making where i want them to be. I was looking for a way via js to change ownerships of said civs randomly on start of the game.

I just realised this gives problems if there are less than 8 players, there would still be extra CC's. So no-go i guess. zzZZzz it's not easy being stupid.

Edited by Grapjas
Link to comment
Share on other sites

13 hours ago, Grapjas said:

What im aiming for is: I want fixed starting places on the map, but randomize to which fixed place the player will be assigned to. This way e.g. player 3 wont always end up on position 3, but can be assigned to position 8, or 5,  etc. However the team members need to be adjacent to eachother. Im not sure i can formulate it clearly than this :unsure:

Ah, that's super straightforward to do. Just assign playerids and playerpositions to your liking as I mentioned on my previous post. For randomizing playerids grouping by team look for `sortPlayers(playerIDs)` in player.js.

4 hours ago, wowgetoffyourcellphone said:

This feature should be a core game feature, IMHO. :) 

Which feature? Player positioning is map dependent.

With A24 would be nice to have specific 1v1, 2v2, 3v3, 4v4 maps with fixed positions but unequal distribution. You could then enable the flag for unequal distribution and you'd be assigned to one spot of the map. Could be diagonally opposed, vertical or horizontal, the opponent wouldn't know your position ahead of time. Biggest issue with that is that harassment capability is greatly impaired with bigger map size, so for a 1v1 I think at most 4 to (arguably) 6 positions can be feasibly done (medium to normal size).

If the feature is enabling this random distribution then it would require a revamp of all maps, which is not a terrible idea but unfeasible in the short time. Map balance is in a worse state than that for example.

This is something from Starcraft 2 that would definitely be super great to have. I thought about putting it into balanced-maps but I'd rather wait for A24 flags (whenever it happens, if I'm still around)

Edited by badosu
Link to comment
Share on other sites

@Grapjas Implementation is simple, store an array of n positions of the coordinates of the starting locations you want (or whatever is the number of max players you want for map).

The algorithm below randomizes position assignments:
 

let fixedPositions = [...]; // your fixed set of positions
let playerPositions = [];

for (int i=0; i<playerIDs.length; i++) {
  fixedPositions = shuffleArray(fixedPositions); // shuffle available positions to take random spot or do whatever you want to assign player positioning
  playerPositions.push(fixedPositions.pop()); // add position to players, pop to take one available position out of the array
}

let playerPlacements = [playerIDs, playerPositions];
// Pass to placePlayerBases

To make it respect adjacency you'd have to make it a bit more complicated, sorting playerIds as I mentioned on post above and sorting fixedPositions with assignment respecting that could work, though I'd require a bit more work to handle edge cases.

Edited by badosu
  • Thanks 1
Link to comment
Share on other sites

Array of Vector2D with the coordinates u want. e.g.
 

let fixedPositions = [
	new Vector2D(x1, y1),
	new Vector2D(x2, y2),
	//...
];

For a programmatic approach see distributePointsonCircularSegment, e.g. for a circle:
 

let points = [];
let angle = [];
let startAngle = 0;
let maxAngle = 2 * Math.PI;
let center = g_Map.getCenter();
let radius = fractionToTiles(0.35);
pointCount = Math.round(pointCount);

for (let i = 0; i < pointCount; ++i)
{
	angle = startAngle + maxAngle * i / Math.max(1, pointCount - 1);
	points[i] = Vector2D.add(center, new Vector2D(radius, 0).rotate(-angle));
}

 

Edited by badosu
  • Thanks 1
Link to comment
Share on other sites

@badosu

let fixedPositions = [    new Vector2D(x:434, y:562),
                        new Vector2D(x:466, y:946),
                        new Vector2D(x:526, y:1392),
                        new Vector2D(x:892, y:1365),
                        new Vector2D(x:1224, y:1390),
                        new Vector2D(x:1334, y:936),
                        new Vector2D(x:1303, y:517),
                        new Vector2D(x:866, y:499), 
                        ]; 

gives me syntax error: missing ) after argument list

Can't find out why. 

Also one probably important thing i forgot to point out, is that i'm not using rmgen, because it's a skirmish map and i assume they can't work together. Starting to think i bit off more than i can chew though, im not a scripter at all. 

 

Link to comment
Share on other sites

Wait, if you are doing this on a skirmish map players will start already with cc. Otherwise you will duplicate ccs, unless u delete autogenerated by map ones like @Stan` said, I'm not sure how to do that.

It would be nice to be able to load a skirmish map on rmgen and scripting player positions and other stuff there. Maybe it's possible dunno, but would be the correct approach for your situation.

Link to comment
Share on other sites

15 hours ago, badosu said:

If it's not rmgen u need to import the libraries

I already tried doing this with: 

Engine.LoadLibrary("rmgen");
Engine.LoadLibrary("rmgen-common");

but it gives me: Engine.LoadLibrary is not a function. 

If i understand this correctly; it's because it's a skirmish map, and not generated from the ground up in js.

----------------------------------------------------------------------------------------------------------------

11 hours ago, badosu said:

Wait, if you are doing this on a skirmish map players will start already with cc.

which is why this was plan A;

On 19/12/2020 at 2:22 PM, Grapjas said:

Plan A: I already have 8 CC's on the current map im making where i want them to be. I was looking for a way via js to change ownerships of said CC's randomly on start of the game.

----------------------------------------------------------------------------------------------------------------

I've tried working with triggers before i tried to incorperate rmgen with a skirmish map. It does somewhat work (at least i was able to spawn something which gave me hope, lol) but has major issues. What i did was delete all the CC's on the map in atlas, then let triggers spawn CC"s at the start of the game. 

The script:

Spoiler

Trigger.prototype.spawnP1 = function()
{
    var p1 = TriggerHelper.SpawnUnitsFromTriggerPoints(
            pickRandom(["A", "B", "C", "D", "E", "F", "G", "H"]), "skirmish/structures/default_civil_centre", 1, 1);
            
};

{
    let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
    cmpTrigger.timerspawnP1 = 0;
    cmpTrigger.DoAfterDelay(cmpTrigger.timerspawnP1, "spawnP1", {});
}

The issues:

  1. This way it's very likely that players will spawn on top of eachother, and i understand why it's happening, but don't know how to fix it. @badosu in your code you popped one position out of the equation if it was used, but idk how to do that here. 
  2. I don't know how to spawn a group of units/building. I've tried understanding maps like danubius and jebel for this, but can't figure out how to create and use templates and make a proper connection to them from this. I've tried 
    Spoiler

    var baseTemplate = [
        { "count": 1, "templates": ["skirmish/structures/default_civil_centre"] },
        { "count": 2, "templates": ["skirmish/units/default_infantry_melee_b"] },
        { "count": 2, "templates": ["skirmish/units/default_infantry_ranged_b"] },
        { "count": 4, "templates": ["skirmish/units/default_support_female_citizen"] }

    ];

    Trigger.prototype.spawnP1 = function()
    {
        var p1 = TriggerHelper.SpawnUnitsFromTriggerPoints(
                pickRandom(["A", "B", "C", "D", "E", "F", "G", "H"]), this.baseTemplate, 1, 1);
    };

    {
        let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
        cmpTrigger.timerspawnP1 = 0.01;
        cmpTrigger.DoAfterDelay(cmpTrigger.timerspawnP1, "spawnP1", {});

    }

    which gives me syntaxerror: missing ] after element list (the format is probably completely wrong though).

  3. The map needs to be compatiable with AI for the people that like to play with them. Right now i get error "petra AI doesnt know how to interpret this map", likely because the AI gets loaded before the CC's are spawned.
  4. Unassigned players CC need to be deleted via js, like @Stan` already said. Or they simply just shouldnt spawn at all if there is a way for the script to check if the player is assigned before placing the CC's. Haven't looked into this yet because the other issues have priority tbh.

----------------------------------------------------------------------------------------------------------------

6 hours ago, Stan` said:

You can save terrain data in the js file I believe.

Is this so that i can use it with rmgen? Also what is stored in terrain data? elevation+textures?

----------------------------------------------------------------------------------------------------------------

This is all i have right now.

Don't laugh at my nooby codes :LOL:, i do plenty myself.

Link to comment
Share on other sites

17 hours ago, Grapjas said:

@badosu in your code you popped one position out of the equation if it was used, but idk how to do that here. 

Same thing, instead of pickrandom:

let availablePositions = ["A", "B", "C", "D", "E", "F", "G", "H"];

Trigger.prototype.spawnP1 = function()
{
    availablePositions = shuffleArray(availablePositions);
    var p1 = TriggerHelper.SpawnUnitsFromTriggerPoints(
            availablePositions.pop(), this.baseTemplate, 1, 1);
}; 

 

17 hours ago, Grapjas said:

I don't know how to spawn a group of units/building. I've tried understanding maps like danubius and jebel for this, but can't figure out how to create and use templates and make a proper connection to them from this.

I never placed structures, units, only gaia stuff. You probably need rmgen for this:
 

new SimpleObject("gaia/geology_metal_mediterranean_slabs", 1, 1, 0, 4).place(
  new Vector2D(x, y),
  playerID,
  false,
  NullConstraint(),
  30 // Retries, never would be necessary for non random maps, should pass on first attempt. Otherwise, learn how to use a placer, like ODiskPlacer on balanced-maps or increase 5th argument on SimpleObject initializer on first line
)

 

Edited by badosu
  • Thanks 1
Link to comment
Share on other sites

@badosu have you got any idea why i cant use the popped position?

Spoiler

 

let availablePositions = ["A", "B", "C", "D", "E", "F", "G", "H"];
let lastPosition = availablePositions.pop();

Trigger.prototype.spawnPlayers = function()
{
    availablePositions = shuffleArray(availablePositions);
    var p1 = TriggerHelper.SpawnUnitsFromTriggerPoints(
            availablePositions.pop(), "skirmish/structures/default_civil_centre", 1, 1);
    TriggerHelper.SpawnUnitsFromTriggerPoints(
            lastPosition, "skirmish/units/default_infantry_melee_b", 2, 1);
    TriggerHelper.SpawnUnitsFromTriggerPoints(
            lastPosition, "skirmish/units/default_infantry_ranged_b", 2, 1);
    TriggerHelper.SpawnUnitsFromTriggerPoints(
            lastPosition, "skirmish/units/default_support_female_citizen", 4, 1);

};

 

Everything spawns, but the units only go for position "H". 

Never mind! figured it out! progessss lol.

Edited by Grapjas
Link to comment
Share on other sites

5 hours ago, badosu said:

What is an 'Unassigned' player?

521682280_image(1).png.067edd44f6bd52ca54c9fb3630ddb54f.png

Unassigned player is neither AI or human player. Though i could still spawn player 2 like this (which is the issue). It's just nothing controlling it. 

I did find where player assignments are being handled @ gui/gamesetup/gamesetup.js. The issue is probably like you said, can't reach that level, because whatever i try it aint working.

I'll keep looking.

Edited by Grapjas
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...