story.cpp

Go to the documentation of this file.
00001 /* $Id: story.cpp 26306 2014-02-06 19:48:19Z zuu $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "story_base.h"
00014 #include "core/pool_func.hpp"
00015 #include "cmd_helper.h"
00016 #include "command_func.h"
00017 #include "company_base.h"
00018 #include "company_func.h"
00019 #include "string_func.h"
00020 #include "date_func.h"
00021 #include "tile_map.h"
00022 #include "goal_type.h"
00023 #include "goal_base.h"
00024 #include "window_func.h"
00025 #include "gui.h"
00026 
00027 
00028 StoryPageElementID _new_story_page_element_id;
00029 StoryPageID _new_story_page_id;
00030 uint32 _story_page_element_next_sort_value;
00031 uint32 _story_page_next_sort_value;
00032 
00033 StoryPageElementPool _story_page_element_pool("StoryPageElement");
00034 StoryPagePool _story_page_pool("StoryPage");
00035 INSTANTIATE_POOL_METHODS(StoryPageElement)
00036 INSTANTIATE_POOL_METHODS(StoryPage)
00037 
00048 static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
00049 {
00050   switch (type) {
00051     case SPET_TEXT:
00052       if (StrEmpty(text)) return false;
00053       break;
00054     case SPET_LOCATION:
00055       if (StrEmpty(text)) return false;
00056       if (!IsValidTile(tile)) return false;
00057       break;
00058     case SPET_GOAL:
00059       if (!Goal::IsValidID((GoalID)reference)) return false;
00060       /* Reject company specific goals on global pages */
00061       if (StoryPage::Get(page_id)->company == INVALID_COMPANY && Goal::Get((GoalID)reference)->company != INVALID_COMPANY) return false;
00062       break;
00063     default:
00064       return false;
00065   }
00066 
00067   return true;
00068 }
00069 
00078 static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
00079 {
00080   switch (pe.type) {
00081     case SPET_TEXT:
00082       pe.text = strdup(text);
00083       break;
00084     case SPET_LOCATION:
00085       pe.text = strdup(text);
00086       pe.referenced_id = tile;
00087       break;
00088     case SPET_GOAL:
00089       pe.referenced_id = (GoalID)reference;
00090       break;
00091     default: NOT_REACHED();
00092   }
00093 }
00094 
00105 CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00106 {
00107   if (!StoryPage::CanAllocateItem()) return CMD_ERROR;
00108 
00109   CompanyID company = (CompanyID)GB(p1, 0, 8);
00110 
00111   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00112   if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
00113 
00114   if (flags & DC_EXEC) {
00115     if (_story_page_pool.items == 0) {
00116       /* Initialize the next sort value variable. */
00117       _story_page_next_sort_value = 0;
00118     }
00119 
00120     StoryPage *s = new StoryPage();
00121     s->sort_value = _story_page_next_sort_value;
00122     s->date = _date;
00123     s->company = company;
00124     if (StrEmpty(text)) {
00125       s->title = NULL;
00126     } else {
00127       s->title = strdup(text);
00128     }
00129 
00130     InvalidateWindowClassesData(WC_STORY_BOOK, -1);
00131     if (StoryPage::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
00132 
00133     _new_story_page_id = s->index;
00134     _story_page_next_sort_value++;
00135   }
00136 
00137   return CommandCost();
00138 }
00139 
00151 CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00152 {
00153   if (!StoryPageElement::CanAllocateItem()) return CMD_ERROR;
00154 
00155   StoryPageID page_id = (CompanyID)GB(p1, 0, 16);
00156   StoryPageElementType type = Extract<StoryPageElementType, 16, 8>(p1);
00157 
00158   /* Allow at most 128 elements per page. */
00159   uint16 element_count = 0;
00160   StoryPageElement *iter;
00161   FOR_ALL_STORY_PAGE_ELEMENTS(iter) {
00162     if (iter->page == page_id) element_count++;
00163   }
00164   if (element_count >= 128) return CMD_ERROR;
00165 
00166   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00167   if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
00168   if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
00169 
00170   if (flags & DC_EXEC) {
00171     if (_story_page_element_pool.items == 0) {
00172       /* Initialize the next sort value variable. */
00173       _story_page_element_next_sort_value = 0;
00174     }
00175 
00176     StoryPageElement *pe = new StoryPageElement();
00177     pe->sort_value = _story_page_element_next_sort_value;
00178     pe->type = type;
00179     pe->page = page_id;
00180     UpdateElement(*pe, tile, p2, text);
00181 
00182     InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
00183 
00184     _new_story_page_element_id = pe->index;
00185     _story_page_element_next_sort_value++;
00186   }
00187 
00188   return CommandCost();
00189 }
00190 
00202 CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00203 {
00204   StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16);
00205 
00206   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00207   if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
00208 
00209   StoryPageElement *pe = StoryPageElement::Get(page_element_id);
00210   StoryPageID page_id = pe->page;
00211   StoryPageElementType type = pe->type;
00212 
00213   if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
00214 
00215   if (flags & DC_EXEC) {
00216     UpdateElement(*pe, tile, p2, text);
00217     InvalidateWindowClassesData(WC_STORY_BOOK, pe->page);
00218   }
00219 
00220   return CommandCost();
00221 }
00222 
00232 CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00233 {
00234   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00235   StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
00236   if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
00237 
00238   if (flags & DC_EXEC) {
00239     StoryPage *p = StoryPage::Get(page_id);
00240     free(p->title);
00241     if (StrEmpty(text)) {
00242       p->title = NULL;
00243     } else {
00244       p->title = strdup(text);
00245     }
00246 
00247     InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
00248   }
00249 
00250   return CommandCost();
00251 }
00252 
00262 CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00263 {
00264   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00265   StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
00266   if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
00267   Date date = (Date)p2;
00268 
00269   if (flags & DC_EXEC) {
00270     StoryPage *p = StoryPage::Get(page_id);
00271     p->date = date;
00272 
00273     InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
00274   }
00275 
00276   return CommandCost();
00277 }
00278 
00289 CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00290 {
00291   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00292   StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
00293   if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
00294 
00295   if (flags & DC_EXEC) {
00296     StoryPage *g = StoryPage::Get(page_id);
00297     if ((g->company != INVALID_COMPANY && g->company == _local_company) || (g->company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowStoryBook(_local_company, page_id);
00298   }
00299 
00300   return CommandCost();
00301 }
00311 CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00312 {
00313   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00314   StoryPageID page_id = (StoryPageID)p1;
00315   if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
00316 
00317   if (flags & DC_EXEC) {
00318     StoryPage *p = StoryPage::Get(page_id);
00319 
00320     StoryPageElement *pe;
00321     FOR_ALL_STORY_PAGE_ELEMENTS(pe) {
00322       if (pe->page == p->index) {
00323         delete pe;
00324       }
00325     }
00326 
00327     delete p;
00328 
00329     InvalidateWindowClassesData(WC_STORY_BOOK, -1);
00330     if (StoryPage::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
00331   }
00332 
00333   return CommandCost();
00334 }
00335 
00345 CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00346 {
00347   if (_current_company != OWNER_DEITY) return CMD_ERROR;
00348   StoryPageElementID page_element_id = (StoryPageElementID)p1;
00349   if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
00350 
00351   if (flags & DC_EXEC) {
00352     StoryPageElement *pe = StoryPageElement::Get(page_element_id);
00353     StoryPageID page_id = pe->page;
00354 
00355     delete pe;
00356 
00357     InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
00358   }
00359 
00360   return CommandCost();
00361 }
00362