Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2005:
[Freeciv-Dev] (PR#10575) city dialog tooltips
Home

[Freeciv-Dev] (PR#10575) city dialog tooltips

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#10575) city dialog tooltips
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 4 Jan 2005 02:53:18 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=10575 >

And here is another patch.  With the new city code this is much easier.
 Only a few special cases remain.

One special case is for tax income.  add_tax_income isn't designed for
uses like this.  Probably we can just have a wrapper for it.

Another special case is for city tithes (gold) and trade routes (trade).
 These must be tallied up and added on manually; they aren't included in
any generic city structures.

A final special case is unhappy-city penalties.  I handled this by
adding a new array holding the unhappy penalty.  Little extra bandwidth
should be required for this because it doesn't change often.

I didn't do anything to the GUI code (in client/gui-gtk-2.0/).  The
original patch didn't apply cleanly so I just adapted it directly. 
Vasco you should probably take a look at this (particularly the RC part).

One stylistic question is whether bonuses of 0 should be included in the
list.  For instance I often see for luxury:

  0   : Citizens
  +0  : Marketplace (+50%)
  +0  : Bank (+50%)
  +0  : Stock Exchange (+50%)
  ===
  0   : Total

which is a bit ugly but more informative.

-jason

? gmon.out
? common/sthNvK7j
Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.55
diff -u -r1.55 citydlg_common.c
--- client/citydlg_common.c     30 Dec 2004 22:11:17 -0000      1.55
+++ client/citydlg_common.c     4 Jan 2005 10:52:14 -0000
@@ -390,6 +390,122 @@
 }
 
 /**************************************************************************
+  Return text describing the production output.
+**************************************************************************/
+void get_city_dialog_output_text(const struct city *pcity,
+                                Output_type_id otype,
+                                char *buf, size_t bufsz)
+{
+  int total = 0;
+  enum effect_type eft = get_output_bonus_effect(otype);
+  int tax[O_COUNT];
+
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              _("%+4d : Citizens\n"), pcity->citizen_base[otype]);
+  total += pcity->citizen_base[otype];
+
+  /* Hack to get around the ugliness of add_tax_income. */
+  memset(tax, 0, O_COUNT * sizeof(*tax));
+  tax[O_TRADE] = pcity->prod[O_TRADE];
+  add_tax_income(city_owner(pcity), tax);
+  tax[O_TRADE] = 0;
+  if (tax[otype] != 0) {
+    cat_snprintf(buf, bufsz, _("%+4d : Taxed from trade\n"), tax[otype]);
+    total += tax[otype];
+  }
+
+  /* Special cases for "bonus" production.  See set_city_production in
+   * city.c. */
+  if (otype == O_TRADE) {
+    int routes = 0, i;
+
+    for (i = 0; i < NUM_TRADEROUTES; i++) {
+      routes += pcity->trade_value[i];
+    }
+    if (routes != 0) {
+      cat_snprintf(buf, bufsz, _("%+4d : Trade routes\n"), routes);
+      total += routes;
+    }
+  } else if (otype == O_GOLD) {
+    int tithes = get_city_tithes_bonus(pcity);
+
+    if (tithes != 0) {
+      cat_snprintf(buf, bufsz, _("%+4d : Building tithes\n"), tithes);
+      total += tithes;
+    }
+  }
+
+  if (eft != EFT_LAST) {
+    int base = total, bonus = 100;
+    struct effect_source_vector sources;
+
+    (void) get_city_bonus_sources(&sources, pcity, eft);
+
+    effect_source_vector_iterate(&sources, s) {
+      int new_total;
+
+      bonus += s->effect_value;
+      new_total = bonus * base / 100;
+      cat_snprintf(buf, bufsz,
+                  _("%+4d : Bonus from %s (%+d%%)\n"),
+                  (new_total - total), get_improvement_name(s->building),
+                  s->effect_value);
+      total = new_total;
+    } effect_source_vector_iterate_end;
+    effect_source_vector_free(&sources);
+  }
+
+  if (pcity->waste[otype] != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Waste\n"), -pcity->waste[otype]);
+    total -= pcity->waste[otype];
+  }
+
+  if (pcity->unhappy_penalty[otype] != 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Disorder\n"), -pcity->unhappy_penalty[otype]);
+    total -= pcity->unhappy_penalty[otype];
+  }
+
+  if (pcity->usage[otype] > 0) {
+    cat_snprintf(buf, bufsz,
+                _("%+4d : Used\n"), -pcity->usage[otype]);
+    total -= pcity->usage[otype];
+  }
+
+  cat_snprintf(buf, bufsz,
+              _("==== : Adds up to\n"));
+  cat_snprintf(buf, bufsz,
+              _("%4d : Total surplus"), pcity->surplus[otype]);
+}
+
+/**************************************************************************
+  Return text describing the pollution output.
+**************************************************************************/
+void get_city_dialog_pollution_text(const struct city *pcity,
+                                   char *buf, size_t bufsz)
+{
+  int pollu, prod, pop, mod;
+
+  pollu = city_pollution_types(pcity, pcity->prod[O_SHIELD],
+                              &prod, &pop, &mod);
+  buf[0] = '\0';
+
+  cat_snprintf(buf, bufsz,
+              "%+4d : Pollution from shields\n", prod);
+  cat_snprintf(buf, bufsz,
+              "%+4d : Pollution from citizens\n", pop);
+  cat_snprintf(buf, bufsz,
+              "%+4d : Pollution modifier\n", mod);
+  cat_snprintf(buf, bufsz,
+              "==== : Adds up to\n");
+  cat_snprintf(buf, bufsz,
+              "%4d : Total surplus", pollu);
+}
+
+/**************************************************************************
   Provide a list of all citizens in the city, in order.  "index"
   should be the happiness index (currently [0..4]; 4 = final
   happiness).  "citizens" should be an array large enough to hold all
Index: client/citydlg_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.h,v
retrieving revision 1.28
diff -u -r1.28 citydlg_common.h
--- client/citydlg_common.h     2 Dec 2004 10:06:58 -0000       1.28
+++ client/citydlg_common.h     4 Jan 2005 10:52:14 -0000
@@ -56,6 +56,12 @@
 void get_city_dialog_production_row(char *buf[], size_t column_size, int id,
                                    bool is_unit, struct city *pcity);
 
+void get_city_dialog_output_text(const struct city *pcity,
+                                Output_type_id otype,
+                                char *buffer, size_t bufsz);
+void get_city_dialog_pollution_text(const struct city *pcity,
+                                   char *buffer, size_t bufsz);
+
 void get_city_citizen_types(struct city *pcity, int index,
                            struct citizen_type *citizens);
 void city_rotate_specialist(struct city *pcity, int citizen_index);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.455
diff -u -r1.455 packhand.c
--- client/packhand.c   21 Dec 2004 03:36:18 -0000      1.455
+++ client/packhand.c   4 Jan 2005 10:52:15 -0000
@@ -449,6 +449,7 @@
   output_type_iterate(o) {
     pcity->surplus[o] = packet->surplus[o];
     pcity->waste[o] = packet->waste[o];
+    pcity->unhappy_penalty[o] = packet->unhappy_penalty[o];
     pcity->prod[o] = packet->prod[o];
     pcity->citizen_base[o] = packet->citizen_base[o];
     pcity->usage[o] = packet->usage[o];
Index: client/gui-gtk-2.0/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/citydlg.c,v
retrieving revision 1.108
diff -u -r1.108 citydlg.c
--- client/gui-gtk-2.0/citydlg.c        21 Dec 2004 04:18:53 -0000      1.108
+++ client/gui-gtk-2.0/citydlg.c        4 Jan 2005 10:52:15 -0000
@@ -128,6 +128,7 @@
     struct unit_node_vector supported_units;
     struct unit_node_vector present_units;
 
+    GtkWidget *info_ebox[NUM_INFO_FIELDS];
     GtkWidget *info_label[NUM_INFO_FIELDS];
   } overview;
  
@@ -141,6 +142,7 @@
     GtkWidget *map_canvas;
     GtkWidget *map_canvas_pixmap;
     GtkWidget *widget;
+    GtkWidget *info_ebox[NUM_INFO_FIELDS];
     GtkWidget *info_label[NUM_INFO_FIELDS];
   } happiness;
 
@@ -186,7 +188,9 @@
 static gboolean keyboard_handler(GtkWidget * widget, GdkEventKey * event,
                                 struct city_dialog *pdialog);
 
-static GtkWidget *create_city_info_table(GtkWidget **info_label);
+static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
+                                        GtkWidget **info_ebox,
+                                        GtkWidget **info_label);
 static void create_and_append_overview_page(struct city_dialog *pdialog);
 static void create_and_append_worklist_page(struct city_dialog *pdialog);
 static void create_and_append_happiness_page(struct city_dialog *pdialog);
@@ -199,7 +203,8 @@
 
 static void city_dialog_update_title(struct city_dialog *pdialog);
 static void city_dialog_update_citizens(struct city_dialog *pdialog);
-static void city_dialog_update_information(GtkWidget **info_label,
+static void city_dialog_update_information(GtkWidget **info_ebox,
+                                          GtkWidget **info_label,
                                            struct city_dialog *pdialog);
 static void city_dialog_update_map(struct city_dialog *pdialog);
 static void city_dialog_update_building(struct city_dialog *pdialog);
@@ -360,7 +365,8 @@
 
   city_dialog_update_title(pdialog);
   city_dialog_update_citizens(pdialog);
-  city_dialog_update_information(pdialog->overview.info_label, pdialog);
+  city_dialog_update_information(pdialog->overview.info_ebox,
+                                pdialog->overview.info_label, pdialog);
   city_dialog_update_map(pdialog);
   city_dialog_update_building(pdialog);
   city_dialog_update_improvement_list(pdialog);
@@ -375,7 +381,8 @@
 
     refresh_worklist(pdialog->production.worklist);
 
-    city_dialog_update_information(pdialog->happiness.info_label, pdialog);
+    city_dialog_update_information(pdialog->happiness.info_ebox,
+                                  pdialog->happiness.info_label, pdialog);
     refresh_happiness_dialog(pdialog->pcity);
 
     refresh_cma_dialog(pdialog->pcity, REFRESH_ALL);
@@ -485,14 +492,93 @@
   return FALSE;
 }
 
+/**************************************************************************
+...
+**************************************************************************/
+static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev,
+                                        gpointer data)
+{
+  gtk_grab_remove(w);
+  gdk_pointer_ungrab(GDK_CURRENT_TIME);
+  gtk_widget_destroy(w);
+  return FALSE;
+}
+
+enum { FIELD_FOOD, FIELD_SHIELD, FIELD_TRADE, FIELD_GOLD, FIELD_LUXURY,
+       FIELD_SCIENCE, FIELD_GRANARY, FIELD_GROWTH, FIELD_CORRUPTION,
+       FIELD_WASTE, FIELD_POLLUTION 
+};
+
+/****************************************************************
+...
+*****************************************************************/
+static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev,
+                               gpointer data)
+{
+  struct city_dialog *pdialog = g_object_get_data(G_OBJECT(w), "pdialog");
+
+  if (ev->button == 1) {
+    GtkWidget *p, *label;
+    char buf[1024];
+    
+    switch (GPOINTER_TO_UINT(data)) {
+    case FIELD_FOOD:
+      get_city_dialog_output_text(pdialog->pcity, O_FOOD, buf, sizeof(buf));
+      break;
+    case FIELD_SHIELD:
+      get_city_dialog_output_text(pdialog->pcity, O_SHIELD,
+                                 buf, sizeof(buf));
+      break;
+    case FIELD_TRADE:
+      get_city_dialog_output_text(pdialog->pcity, O_TRADE, buf, sizeof(buf));
+      break;
+    case FIELD_GOLD:
+      get_city_dialog_output_text(pdialog->pcity, O_GOLD, buf, sizeof(buf));
+      break;
+    case FIELD_SCIENCE:
+      get_city_dialog_output_text(pdialog->pcity, O_SCIENCE,
+                                 buf, sizeof(buf));
+      break;
+    case FIELD_LUXURY:
+      get_city_dialog_output_text(pdialog->pcity, O_LUXURY,
+                                 buf, sizeof(buf));
+      break;
+    case FIELD_POLLUTION:
+      get_city_dialog_pollution_text(pdialog->pcity, buf, sizeof(buf));
+      break;
+    default:
+      return TRUE;
+    }
+    
+    p = gtk_window_new(GTK_WINDOW_POPUP);
+    gtk_widget_set_name(p, "Freeciv");
+    gtk_container_set_border_width(GTK_CONTAINER(p), 4);
+    gtk_window_set_position(GTK_WINDOW(p), GTK_WIN_POS_MOUSE);
+
+    label = gtk_label_new(buf);
+    gtk_widget_set_name(label, "city info label");
+    gtk_container_add(GTK_CONTAINER(p), label);
+    gtk_widget_show_all(p);
+
+    gdk_pointer_grab(p->window, TRUE, GDK_BUTTON_RELEASE_MASK,
+                    NULL, NULL, ev->time);
+    gtk_grab_add(p);
+
+    g_signal_connect_after(p, "button_release_event",
+                           G_CALLBACK(show_info_button_release), NULL);
+  }
+  return TRUE;
+}
 /****************************************************************
  used once in the overview page and once in the happiness page
  **info_label points to the info_label in the respective struct
 ****************************************************************/
-static GtkWidget *create_city_info_table(GtkWidget **info_label)
+static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
+                                        GtkWidget **info_ebox,
+                                        GtkWidget **info_label)
 {
   int i;
-  GtkWidget *hbox, *table, *label;
+  GtkWidget *hbox, *table, *label, *ebox;
 
   static const char *output_label[NUM_INFO_FIELDS] = { N_("Food:"),
     N_("Prod:"),
@@ -526,12 +612,20 @@
     gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, GTK_FILL, 0,
                     0, 0);
 
+    ebox = gtk_event_box_new();
+    g_object_set_data(G_OBJECT(ebox), "pdialog", pdialog);
+    g_signal_connect(ebox, "button_press_event",
+       G_CALLBACK(show_info_popup), GUINT_TO_POINTER(i));
+    info_ebox[i] = ebox;
+
     label = gtk_label_new("");
     info_label[i] = label;
     gtk_widget_set_name(label, "city label");  /* ditto */
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-    gtk_table_attach(GTK_TABLE(table), label, 1, 2, i, i + 1, GTK_FILL, 0,
+    gtk_container_add(GTK_CONTAINER(ebox), label);
+
+    gtk_table_attach(GTK_TABLE(table), ebox, 1, 2, i, i + 1, GTK_FILL, 0,
                     0, 0);
   }
 
@@ -580,7 +674,9 @@
   frame = gtk_frame_new(_("Info"));
   gtk_box_pack_start(GTK_BOX(top), frame, FALSE, FALSE, 0);
 
-  table = create_city_info_table(pdialog->overview.info_label);
+  table = create_city_info_table(pdialog,
+                                pdialog->overview.info_ebox,
+                                pdialog->overview.info_label);
   gtk_container_add(GTK_CONTAINER(frame), table);
 
   frame = gtk_frame_new(_("City map"));
@@ -867,7 +963,9 @@
   align = gtk_alignment_new(0.5, 0.5, 0, 0);
   gtk_container_add(GTK_CONTAINER(vbox), align);
   
-  table = create_city_info_table(pdialog->happiness.info_label);
+  table = create_city_info_table(pdialog,
+                                pdialog->happiness.info_ebox,
+                                pdialog->happiness.info_label);
   gtk_container_add(GTK_CONTAINER(align), table);
 
   gtk_widget_show_all(page);
@@ -1075,6 +1173,9 @@
   }
 }
 
+
+
+
 /****************************************************************
 ...
 *****************************************************************/
@@ -1306,7 +1407,8 @@
 /****************************************************************
 ...
 *****************************************************************/
-static void city_dialog_update_information(GtkWidget **info_label,
+static void city_dialog_update_information(GtkWidget **info_ebox,
+                                          GtkWidget **info_label,
                                            struct city_dialog *pdialog)
 {
   int i, style;
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.300
diff -u -r1.300 city.c
--- common/city.c       4 Jan 2005 08:36:00 -0000       1.300
+++ common/city.c       4 Jan 2005 10:52:15 -0000
@@ -264,7 +264,7 @@
 /**************************************************************************
   Return the effect for the production bonus for this output type.
 **************************************************************************/
-static inline enum effect_type get_output_bonus_effect(Output_type_id otype)
+inline enum effect_type get_output_bonus_effect(Output_type_id otype)
 {
   switch (otype) {
   case O_SHIELD:
@@ -1934,39 +1934,64 @@
 static inline void unhappy_city_check(struct city *pcity)
 {
   if (city_unhappy(pcity)) {
-    pcity->prod[O_FOOD] = MIN(pcity->usage[O_FOOD], pcity->prod[O_FOOD]);
-    pcity->prod[O_SHIELD] = MIN(pcity->usage[O_SHIELD], pcity->prod[O_SHIELD]);
-    pcity->prod[O_GOLD] = 0;
-    pcity->prod[O_SCIENCE] = 0;
+    pcity->unhappy_penalty[O_FOOD]
+      = MAX(pcity->prod[O_FOOD] - pcity->usage[O_FOOD], 0);
+    pcity->unhappy_penalty[O_SHIELD]
+      = MAX(pcity->prod[O_SHIELD] - pcity->usage[O_SHIELD], 0);
+    pcity->unhappy_penalty[O_GOLD] = pcity->prod[O_GOLD];
+    pcity->unhappy_penalty[O_SCIENCE] = pcity->prod[O_SCIENCE];
     /* Trade and luxury are unaffected. */
+
+    output_type_iterate(o) {
+      pcity->prod[o] -= pcity->unhappy_penalty[o];
+    } output_type_iterate_end;
+  } else {
+    memset(pcity->unhappy_penalty, 0,
+          O_COUNT * sizeof(*pcity->unhappy_penalty));
   }
 }
 
 /**************************************************************************
-  Calculate pollution for the city.  The shield_total must be passed in
-  (most callers will want to pass pcity->prod[O_SHIELD]).
+  Calculate the pollution from production and population in the city.
 **************************************************************************/
-int city_pollution(struct city *pcity, int shield_total)
+int city_pollution_types(const struct city *pcity, int shield_total,
+                        int *pollu_prod, int *pollu_pop, int *pollu_mod)
 {
   struct player *pplayer = city_owner(pcity);
-  int mod, pollution;
+  int prod, pop, mod;
 
   /* Add one one pollution per shield, multipled by the bonus. */
-  mod = 100 + get_city_bonus(pcity, EFT_POLLU_PROD_PCT);
-  mod = MAX(0, mod);
-  pollution = shield_total * mod / 100;
+  prod = 100 + get_city_bonus(pcity, EFT_POLLU_PROD_PCT);
+  prod = shield_total * MAX(prod, 0) / 100;
 
   /* Add one 1/4 pollution per citizen per tech, multiplied by the bonus. */
-  mod = 100 + get_city_bonus(pcity, EFT_POLLU_POP_PCT);
-  mod = MAX(0, mod);
-  pollution += (pcity->size
-               * num_known_tech_with_flag(pplayer,
-                                          TF_POPULATION_POLLUTION_INC)
-               * mod) / (4 * 100);
+  pop = 100 + get_city_bonus(pcity, EFT_POLLU_POP_PCT);
+  pop = (pcity->size
+        * num_known_tech_with_flag(pplayer, TF_POPULATION_POLLUTION_INC)
+        * MAX(pop, 0)) / (4 * 100);
 
-  pollution = MAX(0, pollution - 20);
+  /* Then there's a base -20 pollution. */
+  mod = -20;
+
+  if (pollu_prod) {
+    *pollu_prod = prod;
+  }
+  if (pollu_pop) {
+    *pollu_pop = pop;
+  }
+  if (pollu_mod) {
+    *pollu_mod = mod;
+  }
+  return MAX(prod + pop + mod, 0);
+}
 
-  return pollution;
+/**************************************************************************
+  Calculate pollution for the city.  The shield_total must be passed in
+  (most callers will want to pass pcity->shield_prod).
+**************************************************************************/
+int city_pollution(struct city *pcity, int shield_total)
+{
+  return city_pollution_types(pcity, shield_total, NULL, NULL, NULL);
 }
 
 /**************************************************************************
@@ -2462,6 +2487,8 @@
 
   memset(pcity->surplus, 0, O_COUNT * sizeof(*pcity->surplus));
   memset(pcity->waste, 0, O_COUNT * sizeof(*pcity->waste));
+  memset(pcity->unhappy_penalty, 0,
+        O_COUNT * sizeof(*pcity->unhappy_penalty));
   memset(pcity->prod, 0, O_COUNT * sizeof(*pcity->prod));
   memset(pcity->citizen_base, 0, O_COUNT * sizeof(*pcity->citizen_base));
   output_type_iterate(o) {
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.191
diff -u -r1.191 city.h
--- common/city.h       4 Jan 2005 08:36:00 -0000       1.191
+++ common/city.h       4 Jan 2005 10:52:16 -0000
@@ -240,7 +240,8 @@
   /* the productions */
   int surplus[O_MAX]; /* Final surplus in each category. */
   int waste[O_MAX]; /* Waste/corruption in each category. */
-  int prod[O_MAX]; /* Production is total minus waste. */
+  int unhappy_penalty[O_MAX]; /* Penalty from unhappy cities. */
+  int prod[O_MAX]; /* Production is total minus waste and penalty. */
   int citizen_base[O_MAX]; /* Base production from citizens. */
   int usage[O_MAX]; /* Amount of each resource being used. */
 
@@ -362,6 +363,7 @@
 
 const char *get_output_identifier(Output_type_id output);
 const char *get_output_name(Output_type_id output);
+enum effect_type get_output_bonus_effect(Output_type_id otype);
 
 /* properties */
 
@@ -515,6 +517,8 @@
 void get_citizen_output(const struct city *pcity, int *output);
 void add_tax_income(const struct player *pplayer, int *output);
 int get_city_tithes_bonus(const struct city *pcity);
+int city_pollution_types(const struct city *pcity, int shield_total,
+                        int *pollu_prod, int *pollu_pop, int *pollu_mod);
 int city_pollution(struct city *pcity, int shield_total);
 
 /*
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.85
diff -u -r1.85 packets.def
--- common/packets.def  21 Dec 2004 03:36:18 -0000      1.85
+++ common/packets.def  4 Jan 2005 10:52:16 -0000
@@ -401,6 +401,7 @@
 
   SINT16 surplus[O_MAX];
   UINT16 waste[O_MAX];
+  SINT16 unhappy_penalty[O_MAX];
   UINT16 prod[O_MAX];
   SINT16 citizen_base[O_MAX];
   SINT16 usage[O_MAX];
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.296
diff -u -r1.296 citytools.c
--- server/citytools.c  21 Dec 2004 04:18:54 -0000      1.296
+++ server/citytools.c  4 Jan 2005 10:52:17 -0000
@@ -1535,6 +1535,7 @@
   output_type_iterate(o) {
     packet->surplus[o] = pcity->surplus[o];
     packet->waste[o] = pcity->waste[o];
+    packet->unhappy_penalty[o] = pcity->unhappy_penalty[o];
     packet->prod[o] = pcity->prod[o];
     packet->citizen_base[o] = pcity->citizen_base[o];
     packet->usage[o] = pcity->usage[o];

[Prev in Thread] Current Thread [Next in Thread]