I've spent some time researching the problem, and I would like to discuss it. Let's look at vanilla urban terrain mapScript:
- type: URBAN
commands:
- type: addCraft
- type: addLine
label: 1
direction: vertical
executionChances: 50
rects:
- [1, 1, 4, 1]
- type: addLine
label: 2
conditionals: -1
executionChances: 50
direction: horizontal
rects:
- [1, 1, 1, 4]
- type: addLine
conditionals: [-1, -2]
direction: both
rects:
- [1, 1, 4, 4]
- type: addBlock
size: 2
executions: 4
- type: fillArea
blocks: [3, 4, 10, 11, 12, 13, 14]
freqs: [3, 3, 2, 2, 2, 2, 2]
Here rects numbers like [1, 1, 4, 4] suppose you have constant map size, but it is defined in alienDeployment. If we will want to use this script in multiple deployments we will need to make copies of this script for each map size, which makes mod far less manageable, especially if we have complicated scripts. For example, we want to use the complex script for urban maps with map sizes from 40 (where you need to capture single or 2 enemy units) to 80, where there are huge war actions. It would be cool if we can define a number for rect from map size, for example, mapsize - 1. I've thought about it for some time and here what I'm suggesting.
As game expect rect numbers to be integers, we can use negative values for that. As we need to keep 0, you know, as 0, I suggest to treat value '-1' equal to map size, '-2' as map size - 1 and so on (if i < 0; i=mapsize - i + 1).
Thus, suggesting syntax would be like
- type: addCraft
rects:
- [1, 1, -2, -2]
That makes sure we will not place xcom craft near the map border no matter what map sizes are. That can make sense if its map is. for example, a cave exists to all sides, and you don't want it to lead nowhere. Speaking of cave maps, there could be a funny script that will make a cave with no exits outside of the map:
- type: TEST_CAVE_SCRIPT
commands:
- type: addCraft #handle xcom spawn
rects:
- [1, 1, -2, -2]
- type: addLine
direction: both
verticalGroup: 4 #west border group
horizontalGroup: 5 #north border group
crossingGroup: 6 #NW corner group
rects:
- [0, 0, 1, 1] #places it to upper NW map corner
- type: addLine
direction: both
verticalGroup: 7 #east border group
horizontalGroup: 8 #soth border group
crossingGroup: 9 #SE corner group
rects:
- [-2, -2, -1, -1] #places it to upper SE map corner
- type: removeBlock #handle NE corner
rects:
- [-2, 0, -1, 0]
- type: addBlock
rects:
- [-2, 0, -1, 0]
groups: 10
- type: removeBlock #handle SW corner
rects:
- [0, -2, 0, -1]
- type: addBlock
rects:
- [0, -2, 0, -1]
groups: 11
- type: fillArea
rects:
- [1, 1, -2, -2]
groups: [3]
I was looking to code and I'm confused with mapScripts, I'm not sure how ti do that elegant way. Rects processing is called multiple times by commands with a little difference. Probably I should make some method to process negative values before general processing, but i don't know how to insert it to selectPosition method same way and constructions like this look ugly to me:
bool BattlescapeGenerator::removeBlocks(MapScript *command)
{
std::vector<std::pair<int, int> > deleted;
bool success = false;
for (std::vector<SDL_Rect*>::const_iterator k = command->getRects()->begin(); k != command->getRects()->end(); ++k)
{
if ((*k)->x < 0) {
(*k)->x = (*k)->x - _mapsize_x + 1;
}
if ((*k)->y < 0) {
(*k)->y = (*k)->y - _mapsize_y + 1;
}
if ((*k)->w < 0) {
(*k)->w = (*k)->w - _mapsize_x + 1;
}
if ((*k)->h < 0) {
(*k)->h = (*k)->h - _mapsize_y + 1;
}
for (int x = (*k)->x; x != (*k)->x + (*k)->w && x != _mapsize_x / 10; ++x)
{
for (int y = (*k)->y; y != (*k)->y + (*k)->h && y != _mapsize_y / 10; ++y)
I wonder if i can place some processing in getRects method itself, but for it I need to transfer mapsize we have to it as arguments. Also, I think I should not place such calculations to a Mod part. I would be glad for any feedback and if the idea itself is worthful - some coding advice to implement it in a good way.