truelight@988: #include "stdafx.h" truelight@988: #include "ttd.h" truelight@988: #include "table/strings.h" truelight@988: #include "signs.h" truelight@988: #include "saveload.h" truelight@988: #include "command.h" truelight@988: truelight@1283: enum { truelight@1283: /* Max signs: 64000 (4 * 16000) */ truelight@1283: SIGN_POOL_BLOCK_SIZE_BITS = 2, /* In bits, so (1 << 2) == 4 */ truelight@1283: SIGN_POOL_MAX_BLOCKS = 16000, truelight@1283: }; truelight@1283: truelight@1283: /** truelight@1283: * Called if a new block is added to the sign-pool truelight@1283: */ truelight@1283: static void SignPoolNewBlock(uint start_item) truelight@1283: { truelight@1283: SignStruct *ss; truelight@1283: truelight@1283: FOR_ALL_SIGNS_FROM(ss, start_item) truelight@1283: ss->index = start_item++; truelight@1283: } truelight@1283: truelight@1283: /* Initialize the sign-pool */ truelight@1283: MemoryPool _sign_pool = { "Signs", SIGN_POOL_MAX_BLOCKS, SIGN_POOL_BLOCK_SIZE_BITS, sizeof(SignStruct), &SignPoolNewBlock, 0, 0, NULL }; truelight@1283: truelight@988: /** truelight@988: * truelight@988: * Update the coordinate of one sign truelight@988: * truelight@988: */ truelight@988: static void UpdateSignVirtCoords(SignStruct *ss) truelight@988: { truelight@988: Point pt = RemapCoords(ss->x, ss->y, ss->z); truelight@988: SetDParam(0, ss->str); truelight@988: UpdateViewportSignPos(&ss->sign, pt.x, pt.y - 6, STR_2806); truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@990: * Update the coordinates of all signs truelight@988: * truelight@988: */ tron@1093: void UpdateAllSignVirtCoords(void) truelight@988: { truelight@988: SignStruct *ss; truelight@988: truelight@988: FOR_ALL_SIGNS(ss) truelight@988: if (ss->str != 0) truelight@988: UpdateSignVirtCoords(ss); truelight@988: truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Marks the region of a sign as dirty truelight@988: * truelight@988: * @param ss Pointer to the SignStruct truelight@988: */ truelight@988: static void MarkSignDirty(SignStruct *ss) truelight@988: { truelight@988: MarkAllViewportsDirty( truelight@988: ss->sign.left - 6, truelight@988: ss->sign.top - 3, truelight@988: ss->sign.left + ss->sign.width_1 * 4 + 12, truelight@988: ss->sign.top + 45); truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Allocates a new sign truelight@988: * truelight@988: * @return The pointer to the new sign, or NULL if there is no more free space truelight@988: */ tron@1093: static SignStruct *AllocateSign(void) truelight@988: { truelight@988: SignStruct *s; truelight@988: FOR_ALL_SIGNS(s) truelight@988: if (s->str == 0) truelight@988: return s; truelight@988: truelight@1283: /* Check if we can add a block to the pool */ truelight@1283: if (AddBlockToPool(&_sign_pool)) truelight@1283: return AllocateSign(); truelight@1283: truelight@988: return NULL; truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@990: * Place a sign at the given x/y truelight@988: * dominik@1165: * @param p1 player number truelight@988: * @param p2 not used truelight@988: */ truelight@988: int32 CmdPlaceSign(int x, int y, uint32 flags, uint32 p1, uint32 p2) truelight@988: { truelight@988: SignStruct *ss; truelight@988: truelight@988: /* Try to locate a new sign */ truelight@988: ss = AllocateSign(); truelight@988: if (ss == NULL) truelight@988: return_cmd_error(STR_2808_TOO_MANY_SIGNS); truelight@988: truelight@988: /* When we execute, really make the sign */ truelight@988: if (flags & DC_EXEC) { truelight@988: ss->str = STR_280A_SIGN; truelight@988: ss->x = x; truelight@988: ss->y = y; dominik@1165: ss->owner = p1; truelight@988: ss->z = GetSlopeZ(x,y); truelight@988: UpdateSignVirtCoords(ss); truelight@988: MarkSignDirty(ss); truelight@988: _new_sign_struct = ss; truelight@988: } truelight@988: truelight@988: return 0; truelight@988: } truelight@988: truelight@988: /** truelight@988: * Rename a sign truelight@988: * truelight@988: * @param sign_id Index of the sign dominik@1165: * @param new owner, if OWNER_NONE, sign will be removed truelight@988: */ dominik@1165: int32 CmdRenameSign(int x, int y, uint32 flags, uint32 sign_id, uint32 owner) truelight@988: { truelight@988: StringID str; truelight@988: SignStruct *ss; truelight@988: truelight@988: /* If GetDParam(0) == nothing, we delete the sign */ dominik@1165: if (GetDParam(0) != 0 && owner != OWNER_NONE) { truelight@988: /* Create the name */ tron@1328: str = AllocateName((const char*)_decode_parameters, 0); truelight@988: if (str == 0) truelight@988: return CMD_ERROR; truelight@988: truelight@988: if (flags & DC_EXEC) { truelight@988: ss = GetSign(sign_id); truelight@988: truelight@988: MarkSignDirty(ss); truelight@988: truelight@988: /* Delete the old name */ truelight@988: DeleteName(ss->str); truelight@988: /* Assign the new one */ truelight@988: ss->str = str; dominik@1165: ss->owner = owner; truelight@988: truelight@988: /* Update */ truelight@988: UpdateSignVirtCoords(ss); truelight@988: MarkSignDirty(ss); truelight@988: } else { truelight@988: /* Free the name, because we did not assign it yet */ truelight@988: DeleteName(str); truelight@988: } truelight@988: } else { truelight@988: /* Delete sign */ truelight@988: if (flags & DC_EXEC) { truelight@988: ss = GetSign(sign_id); truelight@988: truelight@988: /* Delete the name */ truelight@988: DeleteName(ss->str); truelight@988: ss->str = 0; truelight@988: truelight@988: MarkSignDirty(ss); truelight@988: } truelight@988: } truelight@988: truelight@988: return 0; truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Callback function that is called after a sign is placed truelight@988: * truelight@988: */ truelight@988: void CcPlaceSign(bool success, uint tile, uint32 p1, uint32 p2) truelight@988: { truelight@988: if (success) { truelight@988: ShowRenameSignWindow(_new_sign_struct); truelight@988: ResetObjectToPlace(); truelight@988: } truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * PlaceProc function, called when someone pressed the button if the truelight@988: * sign-tool is selected truelight@988: * truelight@988: */ truelight@988: void PlaceProc_Sign(uint tile) truelight@988: { dominik@1165: DoCommandP(tile, _current_player, 0, CcPlaceSign, CMD_PLACE_SIGN | CMD_MSG(STR_2809_CAN_T_PLACE_SIGN_HERE)); truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Initialize the signs truelight@988: * truelight@988: */ tron@1093: void InitializeSigns(void) truelight@988: { truelight@1283: CleanPool(&_sign_pool); truelight@1283: AddBlockToPool(&_sign_pool); truelight@988: } truelight@988: truelight@988: static const byte _sign_desc[] = { truelight@988: SLE_VAR(SignStruct,str, SLE_UINT16), truelight@988: SLE_CONDVAR(SignStruct,x, SLE_FILE_I16 | SLE_VAR_I32, 0, 4), truelight@988: SLE_CONDVAR(SignStruct,y, SLE_FILE_I16 | SLE_VAR_I32, 0, 4), truelight@988: SLE_CONDVAR(SignStruct,x, SLE_INT32, 5, 255), truelight@988: SLE_CONDVAR(SignStruct,y, SLE_INT32, 5, 255), dominik@1201: SLE_CONDVAR(SignStruct,owner, SLE_UINT8, 6, 255), truelight@988: SLE_VAR(SignStruct,z, SLE_UINT8), truelight@988: SLE_END() truelight@988: }; truelight@988: truelight@988: /** truelight@988: * truelight@988: * Save all signs truelight@988: * truelight@988: */ tron@1093: static void Save_SIGN(void) truelight@988: { truelight@1283: SignStruct *ss; truelight@988: truelight@1283: FOR_ALL_SIGNS(ss) { truelight@988: /* Don't save empty signs */ truelight@1283: if (ss->str != 0) { truelight@1283: SlSetArrayIndex(ss->index); truelight@1283: SlObject(ss, _sign_desc); truelight@988: } truelight@988: } truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Load all signs truelight@988: * truelight@988: */ tron@1093: static void Load_SIGN(void) truelight@988: { truelight@988: int index; truelight@988: while ((index = SlIterateArray()) != -1) { truelight@1283: SignStruct *ss; truelight@988: truelight@1283: if (!AddBlockIfNeeded(&_sign_pool, index)) truelight@1283: error("Signs: failed loading savegame: too many signs"); truelight@1283: truelight@1283: ss = GetSign(index); truelight@1283: SlObject(ss, _sign_desc); truelight@988: } truelight@988: } truelight@988: truelight@988: const ChunkHandler _sign_chunk_handlers[] = { truelight@988: { 'SIGN', Save_SIGN, Load_SIGN, CH_ARRAY | CH_LAST}, truelight@988: };