diff --git a/config/fxdata/terrain.cfg b/config/fxdata/terrain.cfg
index 25de5e0b84..a66b2f7056 100644
--- a/config/fxdata/terrain.cfg
+++ b/config/fxdata/terrain.cfg
@@ -1086,11 +1086,22 @@ Messages = 0 0 0
; Sound sample playing in a loop when hovering over it on screen.
AmbientSndSample = 0
; Algorithm used to compute room capacity:
-; slabs_all_only, slabs_all_wth_effcncy, slabs_div2_wth_effcncy, gold_slabs_wth_effcncy, gold_slabs_full, none.
+; slabs_all_only - One capacity per slab.
+; slabs_all_wth_effcncy - Capacity is reduced when the room is less effecient.
+; slabs_no_min_wth_effcncy - Same as above, but without a minimum capacity of 1.
+; slabs_div2_wth_effcncy - Capacity is reduced by room effeciency, then divided by two.
+; slabs_div2_nomin_effcncy - Same as above, but without a minimum capacity of 1.
+; slabs_mul2_wth_effcncy - Capacity is reduced by room effeciency, then multiplied by two.
+; slabs_pow2_wth_effcncy - Capacity is reduced by the square of room effeciency, ie 50% efficient means 25% capacity.
+; gold_slabs_wth_effcncy - Capacity is reduced by room effeciency, then multiplied by gold hoard types (5).
+; gold_slabs_full - One capacity per slab, then multiplied by gold hoard types.
+; none - No capacity.
TotalCapacity = none
; Algorithm used to used storage space and used worker space:
; count_gold_hoardes_in_room, count_books_in_room, count_workers_in_room, count_crates_in_room, count_bodies_in_room, count_food_in_room, count_lair_occupants, none.
UsedCapacity = none none
+; Slab that it also receives full efficiency bonus from.
+SlabSynergy = none
; Height in cubes at which storage is created. Negative values for any.
StorageHeight = 0
; Sprite icon of the room, large size and medium size.
@@ -1113,6 +1124,7 @@ Messages = 0 0 0
AmbientSndSample = 0
TotalCapacity = slabs_all_only
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 0
SymbolSprites = 0 0
PointerSprites = 0
@@ -1131,6 +1143,7 @@ Messages = 39 24 35
AmbientSndSample = 0
TotalCapacity = gold_slabs_wth_effcncy
UsedCapacity = gold_hoardes_in_room none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 29 57
PointerSprites = 25
@@ -1149,6 +1162,7 @@ Messages = 0 25 0
AmbientSndSample = 0
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = books_in_room workers_in_room
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 33 61
PointerSprites = 27
@@ -1168,6 +1182,7 @@ Messages = 0 26 0
AmbientSndSample = 0
TotalCapacity = slabs_all_wth_effcncy
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 37 65
PointerSprites = 29
@@ -1187,6 +1202,7 @@ Messages = 0 27 0
AmbientSndSample = 0
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 35 63
PointerSprites = 28
@@ -1205,6 +1221,7 @@ Messages = 0 28 0
AmbientSndSample = 85
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 39 67
PointerSprites = 30
@@ -1222,6 +1239,7 @@ Properties = CANNOT_BE_CLAIMED CANNOT_BE_SOLD CANNOT_VANDALIZE HAS_NO_ENSIGN
AmbientSndSample = 0
TotalCapacity = none
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 2
SymbolSprites = 0 0
PointerSprites = 0
@@ -1240,6 +1258,7 @@ Messages = 0 29 0
AmbientSndSample = 86
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = crates_in_room workers_in_room
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 47 75
PointerSprites = 34
@@ -1258,6 +1277,7 @@ Messages = 0 30 0
AmbientSndSample = 156
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 49 77
PointerSprites = 35
@@ -1276,6 +1296,7 @@ Messages = 0 31 0
AmbientSndSample = 155
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 2
SymbolSprites = 45 73
PointerSprites = 33
@@ -1295,6 +1316,7 @@ Messages = 0 32 0
AmbientSndSample = 45
TotalCapacity = slabs_all_only
UsedCapacity = bodies_in_room none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 43 71
PointerSprites = 32
@@ -1313,6 +1335,7 @@ Messages = 0 33 0
AmbientSndSample = 0
TotalCapacity = slabs_div2_wth_effcncy
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 2
SymbolSprites = 41 69
PointerSprites = 31
@@ -1331,6 +1354,7 @@ Messages = 41 22 34
AmbientSndSample = 0
TotalCapacity = slabs_all_wth_effcncy
UsedCapacity = food_in_room none
+SlabSynergy = none
StorageHeight = 0
SymbolSprites = 31 59
PointerSprites = 26
@@ -1349,6 +1373,7 @@ Messages = 40 23 36
AmbientSndSample = 0
TotalCapacity = slabs_all_wth_effcncy
UsedCapacity = lair_occupants none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 51 79
PointerSprites = 36
@@ -1367,6 +1392,7 @@ Messages = 0 0 0
AmbientSndSample = 0
TotalCapacity = none
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 1
SymbolSprites = 53 81
PointerSprites = 37
@@ -1385,6 +1411,7 @@ Messages = 0 0 0
AmbientSndSample = 0
TotalCapacity = slabs_all_only
UsedCapacity = none none
+SlabSynergy = none
StorageHeight = 2
SymbolSprites = 55 83
PointerSprites = 38
diff --git a/keeperfx_vs2010.vcxproj b/keeperfx_vs2010.vcxproj
index 20ccca5ff7..5f8b340e85 100644
--- a/keeperfx_vs2010.vcxproj
+++ b/keeperfx_vs2010.vcxproj
@@ -226,6 +226,7 @@
+
diff --git a/keeperfx_vs2010.vcxproj.filters b/keeperfx_vs2010.vcxproj.filters
index 55574e890b..54560434d6 100644
--- a/keeperfx_vs2010.vcxproj.filters
+++ b/keeperfx_vs2010.vcxproj.filters
@@ -735,6 +735,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/config_terrain.c b/src/config_terrain.c
index bac86d19a8..c41dd1a30d 100644
--- a/src/config_terrain.c
+++ b/src/config_terrain.c
@@ -80,9 +80,10 @@ const struct NamedCommand terrain_room_commands[] = {
{"PANELTABINDEX", 12},
{"TOTALCAPACITY", 13},
{"USEDCAPACITY", 14},
- {"AMBIENTSNDSAMPLE", 15},
- {"ROLES", 16},
- {"STORAGEHEIGHT", 17},
+ {"SLABSYNERGY", 15},
+ {"AMBIENTSNDSAMPLE", 16},
+ {"ROLES", 17},
+ {"STORAGEHEIGHT", 18},
{NULL, 0},
};
@@ -129,17 +130,25 @@ const struct NamedCommand room_roles_desc[] = {
extern void count_slabs_all_only(struct Room *room);
extern void count_slabs_all_wth_effcncy(struct Room *room);
+extern void count_slabs_no_min_wth_effcncy(struct Room *room);
extern void count_slabs_div2_wth_effcncy(struct Room *room);
+extern void count_slabs_div2_nomin_effcncy(struct Room *room);
+extern void count_slabs_mul2_wth_effcncy(struct Room *room);
+extern void count_slabs_pow2_wth_effcncy(struct Room *room);
extern void count_gold_slabs_wth_effcncy(struct Room *room);
extern void count_gold_slabs_full(struct Room *room);
const struct NamedCommand terrain_room_total_capacity_func_type[] = {
{"slabs_all_only", 1},
{"slabs_all_wth_effcncy", 2},
- {"slabs_div2_wth_effcncy", 3},
- {"gold_slabs_wth_effcncy", 4},
- {"gold_slabs_full", 5},
- {"none", 6},
+ {"slabs_no_min_wth_effcncy",3},
+ {"slabs_div2_wth_effcncy", 4},
+ {"slabs_div2_nomin_effcncy",5},
+ {"slabs_mul2_wth_effcncy", 6},
+ {"slabs_pow2_wth_effcncy", 7},
+ {"gold_slabs_wth_effcncy", 8},
+ {"gold_slabs_full", 9},
+ {"none", 10},
{NULL, 0},
};
@@ -147,7 +156,11 @@ Room_Update_Func terrain_room_total_capacity_func_list[] = {
NULL,
count_slabs_all_only,
count_slabs_all_wth_effcncy,
+ count_slabs_no_min_wth_effcncy,
count_slabs_div2_wth_effcncy,
+ count_slabs_div2_nomin_effcncy,
+ count_slabs_mul2_wth_effcncy,
+ count_slabs_pow2_wth_effcncy,
count_gold_slabs_wth_effcncy,
count_gold_slabs_full,
NULL,
@@ -1083,7 +1096,27 @@ TbBool parse_terrain_room_blocks(char *buf, long len, const char *config_textnam
COMMAND_TEXT(cmd_num),block_buf,config_textname);
}
break;
- case 15: // AMBIENTSNDSAMPLE
+ case 15: // SLABSYNERGY
+ if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0)
+ {
+ if ((strcasecmp(word_buf, "none") == 0)) {
+ roomst->synergy_slab = -2;
+ n++;
+ }
+ k = get_id(slab_desc, word_buf);
+ if (k >= 0)
+ {
+ roomst->synergy_slab = k;
+ n++;
+ }
+ }
+ if (n < 1)
+ {
+ CONFWRNLOG("Incorrect value of \"%s\" parameter in [%s] block of %s file.",
+ COMMAND_TEXT(cmd_num),block_buf,config_textname);
+ }
+ break;
+ case 16: // AMBIENTSNDSAMPLE
if (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0)
{
k = atoi(word_buf);
@@ -1095,11 +1128,12 @@ TbBool parse_terrain_room_blocks(char *buf, long len, const char *config_textnam
}
if (n < 1)
{
+ roomst->synergy_slab = -3;
CONFWRNLOG("Incorrect value of \"%s\" parameter in [%s] block of %s file.",
COMMAND_TEXT(cmd_num),block_buf,config_textname);
}
break;
- case 16: // ROLES
+ case 17: // ROLES
roomst->roles = RoRoF_None;
while (get_conf_parameter_single(buf,&pos,len,word_buf,sizeof(word_buf)) > 0)
{
@@ -1113,7 +1147,7 @@ TbBool parse_terrain_room_blocks(char *buf, long len, const char *config_textnam
}
}
break;
- case 17: // STORAGEHEIGHT
+ case 18: // STORAGEHEIGHT
if (get_conf_parameter_single(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
{
k = atoi(word_buf);
diff --git a/src/config_terrain.h b/src/config_terrain.h
index b57e5d0206..56af55cd5c 100644
--- a/src/config_terrain.h
+++ b/src/config_terrain.h
@@ -140,6 +140,7 @@ struct RoomConfigStats {
TextStringId tooltip_stridx;
long creature_creation_model;
SlabKind assigned_slab;
+ SlabKind synergy_slab;
char storage_height;
unsigned long flags;
RoomRole roles;
@@ -177,7 +178,7 @@ extern const struct NamedCommand terrain_room_properties_commands[];
extern const struct NamedCommand room_roles_desc[];
extern const struct NamedCommand terrain_room_total_capacity_func_type[];
extern const struct NamedCommand terrain_room_used_capacity_func_type[];
-extern Room_Update_Func terrain_room_total_capacity_func_list[8];
+extern Room_Update_Func terrain_room_total_capacity_func_list[12];
extern Room_Update_Func terrain_room_used_capacity_func_list[10];
/******************************************************************************/
diff --git a/src/lvl_script_commands.c b/src/lvl_script_commands.c
index f92ce76e6a..879ee6324a 100644
--- a/src/lvl_script_commands.c
+++ b/src/lvl_script_commands.c
@@ -286,7 +286,8 @@ const struct NamedCommand room_config_desc[] = {
{"Roles", 13},
{"TotalCapacity", 14},
{"UsedCapacity", 15},
- {"StorageHeight", 16},
+ {"SlabSynergy", 16},
+ {"StorageHeight", 17},
{NULL, 0},
};
@@ -1217,7 +1218,7 @@ static void set_room_configuration_check(const struct ScriptLine* scline)
}
value->shorts[2] = newvalue;
}
- else if (roomvar == 10) // SlabAssign
+ else if ((roomvar == 10) || (roomvar == 16)) // SlabAssign & SlabSynergy
{
newvalue = get_id(slab_desc, valuestring);
if (newvalue == -1)
@@ -2030,7 +2031,11 @@ static void set_room_configuration_process(struct ScriptContext *context)
roomst->update_workers_in_room = terrain_room_used_capacity_func_list[value2];
reinitialise_rooms_of_kind(room_type);
break;
- case 16: // StorageHeight
+ case 16: // SlabSynergy
+ roomst->synergy_slab = value;
+ recalculate_effeciency_for_rooms_of_kind(room_type);
+ break;
+ case 17: // StorageHeight
roomst->storage_height = value;
break;
default:
diff --git a/src/room_data.c b/src/room_data.c
index 3e55ccc5b5..8394e8f1ca 100644
--- a/src/room_data.c
+++ b/src/room_data.c
@@ -63,7 +63,11 @@ extern "C" {
/******************************************************************************/
void count_slabs_all_only(struct Room *room);
void count_slabs_all_wth_effcncy(struct Room *room);
+void count_slabs_no_min_wth_effcncy(struct Room *room);
void count_slabs_div2_wth_effcncy(struct Room *room);
+void count_slabs_div2_nomin_effcncy(struct Room *room);
+void count_slabs_mul2_wth_effcncy(struct Room *room);
+void count_slabs_pow2_wth_effcncy(struct Room *room);
void count_workers_in_room(struct Room *room);
long find_random_valid_position_for_item_in_different_room_avoiding_object(struct Thing* thing, struct Room* skip_room, struct Coord3d* pos);
/******************************************************************************/
@@ -465,7 +469,16 @@ void count_slabs_all_wth_effcncy(struct Room *room)
unsigned long count = room->slabs_count * ((long)room->efficiency);
count = (count/ROOM_EFFICIENCY_MAX);
if (count <= 1)
- count = 1;
+ count = 1;
+ room->total_capacity = count;
+}
+
+void count_slabs_no_min_wth_effcncy(struct Room *room)
+{
+ unsigned long count = room->slabs_count * ((long)room->efficiency);
+ count = (count/ROOM_EFFICIENCY_MAX);
+ if (count < 1)
+ count = 0;
room->total_capacity = count;
}
@@ -478,6 +491,33 @@ void count_slabs_div2_wth_effcncy(struct Room *room)
room->total_capacity = count;
}
+void count_slabs_div2_nomin_effcncy(struct Room *room)
+{
+ unsigned long count = room->slabs_count * ((long)room->efficiency);
+ count = ((count/ROOM_EFFICIENCY_MAX) >> 1);
+ if (count < 1)
+ count = 0;
+ room->total_capacity = count;
+}
+
+void count_slabs_mul2_wth_effcncy(struct Room *room)
+{
+ unsigned long count = room->slabs_count * ((long)room->efficiency);
+ count = ((count/ROOM_EFFICIENCY_MAX) << 1);
+ if (count <= 1)
+ count = 1;
+ room->total_capacity = count;
+}
+
+void count_slabs_pow2_wth_effcncy(struct Room *room)
+{
+ unsigned long count = room->slabs_count * ((long)room->efficiency) * ((long)room->efficiency);
+ count = (count/ROOM_EFFICIENCY_MAX/ROOM_EFFICIENCY_MAX);
+ if (count <= 1)
+ count = 1;
+ room->total_capacity = count;
+}
+
void delete_room_structure(struct Room *room)
{
if (room_is_invalid(room))
@@ -1012,6 +1052,42 @@ unsigned short i_can_allocate_free_room_structure(void)
}
+
+/**
+ * Recalculates all players rooms of specific kind.
+ * @param rkind
+ * @return Total amount of rooms which were reinitialized.
+ */
+long recalculate_effeciency_for_rooms_of_kind(RoomKind rkind)
+{
+ unsigned int k = 0;
+ for (unsigned int n = 0; n < DUNGEONS_COUNT; n++)
+ {
+ struct Dungeon* dungeon = get_dungeon(n);
+ unsigned int i = dungeon->room_kind[rkind];
+ while (i != 0)
+ {
+ struct Room* room = room_get(i);
+ if (room_is_invalid(room))
+ {
+ ERRORLOG("Jump to invalid room detected");
+ break;
+ }
+ i = room->next_of_owner;
+ // Per-room code starts
+ set_room_efficiency(room);
+ // Per-room code ends
+ k++;
+ if (k > ROOMS_COUNT)
+ {
+ ERRORLOG("Infinite loop detected when sweeping rooms list");
+ break;
+ }
+ }
+ }
+ return k;
+}
+
/**
* Re-initializes all players rooms of specific kind.
* @param rkind
@@ -1127,7 +1203,7 @@ long calculate_cummulative_room_slabs_effeciency(const struct Room *room)
while (i != 0)
{
// Per room tile code
- score += calculate_effeciency_score_for_room_slab(i, room->owner);
+ score += calculate_effeciency_score_for_room_slab(i, room->owner, get_room_kind_stats(room->kind)->synergy_slab);
// Per room tile code ends
i = get_next_slab_number_in_room(i); // It would be better to have this before per-tile block, but we need old value
k++;
diff --git a/src/room_data.h b/src/room_data.h
index b8f129a6c1..ffc3d45747 100644
--- a/src/room_data.h
+++ b/src/room_data.h
@@ -239,6 +239,7 @@ void destroy_dungeon_heart_room(PlayerNumber plyr_idx, const struct Thing *heart
void update_room_total_capacity(struct Room *room);
long reinitialise_rooms_of_kind(RoomKind rkind);
+long recalculate_effeciency_for_rooms_of_kind(RoomKind rkind);
TbBool find_random_valid_position_for_thing_in_room_avoiding_object_excluding_room_slab(struct Thing *thing, struct Room *room, struct Coord3d *pos, long slbnum);
diff --git a/src/slab_data.c b/src/slab_data.c
index a79e74cb5f..dc4202af38 100644
--- a/src/slab_data.c
+++ b/src/slab_data.c
@@ -462,7 +462,7 @@ SlabKind find_core_slab_type(MapSlabCoord slb_x, MapSlabCoord slb_y)
return corekind;
}
-long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNumber plyr_idx)
+long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNumber plyr_idx, SlabKind synergy_slab_num)
{
TbBool is_room_inside = true;
long eff_score = 0;
@@ -478,6 +478,9 @@ long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNu
MapSlabCoord slb_y = slb_num_decode_y(round_slab_num);
// Per slab code
if ((slabmap_owner(round_slb) == slabmap_owner(slb)) && (round_slb->kind == slb->kind))
+ {
+ eff_score += 2;
+ } else if(((slabmap_owner(round_slb) == slabmap_owner(slb)) || !(get_slab_kind_attrs(synergy_slab_num)->is_ownable)) && (round_slb->kind == synergy_slab_num))
{
eff_score += 2;
} else
diff --git a/src/slab_data.h b/src/slab_data.h
index 7bb57afe12..4b4529dd05 100644
--- a/src/slab_data.h
+++ b/src/slab_data.h
@@ -152,7 +152,7 @@ PlayerNumber get_slab_owner_thing_is_on(const struct Thing *thing);
unsigned long slabmap_wlb(struct SlabMap *slb);
void slabmap_set_wlb(struct SlabMap *slb, unsigned long wlb_type);
SlabCodedCoords get_next_slab_number_in_room(SlabCodedCoords slab_num);
-long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNumber plyr_idx);
+long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNumber plyr_idx, SlabKind synergy_slab_num);
TbBool slab_is_safe_land(PlayerNumber plyr_idx, MapSlabCoord slb_x, MapSlabCoord slb_y);
TbBool slab_is_door(MapSlabCoord slb_x, MapSlabCoord slb_y);