rendered paste bodyIndex: src/client/campaign/cp_messageoptions.c===================================================================--- src/client/campaign/cp_messageoptions.c (revision 24881)+++ src/client/campaign/cp_messageoptions.c (working copy)@@ -55,7 +55,7 @@ N_("ufo_spotted"), N_("ufo_signal_lost"), N_("ufo_attacking"),-+ N_("monthly_report") }; CASSERT(lengthof(nt_strings) == NT_NUM_NOTIFYTYPE); Index: src/client/campaign/cp_messageoptions.h===================================================================--- src/client/campaign/cp_messageoptions.h (revision 24881)+++ src/client/campaign/cp_messageoptions.h (working copy)@@ -52,6 +52,7 @@ NT_UFO_SPOTTED, NT_UFO_SIGNAL_LOST, NT_UFO_ATTACKING,+ NT_MONTHLY_REPORT, NT_NUM_NOTIFYTYPE } notify_t;Index: src/client/campaign/cp_event.c===================================================================--- src/client/campaign/cp_event.c (revision 24881)+++ src/client/campaign/cp_event.c (working copy)@@ -142,6 +142,7 @@ {"body", V_TRANSLATION_STRING, offsetof(eventMail_t, body), 0}, {"icon", V_CLIENT_HUNK_STRING, offsetof(eventMail_t, icon), 0}, {"model", V_CLIENT_HUNK_STRING, offsetof(eventMail_t, model), 0},+ {"notifytype", V_CLIENT_HUNK_STRING, offsetof(eventMail_t, notifyType), 0}, {NULL, 0, 0, 0} };@@ -224,6 +225,7 @@ const char *eventMailId; eventMail_t* eventMail; message_t *m;+ notify_t nt = NT_NUM_NOTIFYTYPE; char dateBuf[MAX_VAR] = ""; if (Cmd_Argc() < 2) {@@ -253,7 +255,16 @@ } /* the subject double %s: see UP_SetMailHeader */- m = MS_AddNewMessage("", va(_("You've got a new mail: %s"), _(eventMail->subject)), qfalse, MSG_EVENT, NULL);+ if (eventMail->notifyType)+ for(nt = 0; nt < NT_NUM_NOTIFYTYPE; nt++)+ if (!strcmp(eventMail->notifyType, nt_strings[nt]))+ break;+ Com_Printf("found (%i)\n", nt);+ if (nt < NT_NUM_NOTIFYTYPE)+ m = MSO_CheckAddNewMessage(nt, "", va(_("You've got a new mail: %s"), _(eventMail->subject)), qfalse, MSG_EVENT, NULL);+ else+ m = MS_AddNewMessage("", va(_("You've got a new mail: %s"), _(eventMail->subject)), qfalse, MSG_EVENT, NULL);+ if (m) m->eventMail = eventMail; elseIndex: src/client/campaign/cp_event.h===================================================================--- src/client/campaign/cp_event.h (revision 24881)+++ src/client/campaign/cp_event.h (working copy)@@ -47,6 +47,7 @@ char *body; /**< the body of the event mail */ char *icon; /**< icon in the mailclient */ char *model; /**< model name of the sender */+ char *notifyType; /**< notification type dor message options */ qboolean read; /**< already read the mail? */ } eventMail_t; Index: src/client/campaign/cp_nations.c===================================================================--- src/client/campaign/cp_nations.c (revision 24881)+++ src/client/campaign/cp_nations.c (working copy)@@ -41,101 +41,92 @@ void CP_NationHandleBudget (void) { int i, j;- char message[1024]; int cost;- int initial_credits = ccs.credits;+ int totalIncome = 0;+ int totalExpenditure = 0;+ int initialCredits = ccs.credits;+ static char mailBuffer[4096];+ eventMail_t *mail;+ dateLong_t date; /* Refreshes the pilot global list. Pilots who are already hired are unchanged, but all other * pilots are replaced. The new pilots is evenly distributed between the nations that are happy (happiness > 0). */ E_RefreshUnhiredEmployeeGlobalList(EMPL_PILOT, qtrue); + mail = CL_NewEventMail("monthly_financial_report", va("monthly_financial_report%i", ccs.date.sec), NULL);+ if (!mail)+ Com_Error(ERR_DROP, "UR_SendMail: monthly_financial_report wasn't found");++ strncpy(mailBuffer, _("^BMonthly Financial and Personel Report\n\n"), lengthof(mailBuffer));+ strncat(mailBuffer, _("^BIncomes\n"), lengthof(mailBuffer));+ for (i = 0; i < ccs.numNations; i++) { nation_t *nation = &ccs.nations[i]; const int funding = NAT_GetFunding(nation, 0);- int new_scientists = 0, new_soldiers = 0, new_workers = 0;- CL_UpdateCredits(ccs.credits + funding);+ const int lastFunding = NAT_GetFunding(nation, 2); - for (j = 0; 0.25 + j < (float) nation->maxScientists * nation->stats[0].happiness * nation->stats[0].happiness; j++) {- /* Create a scientist, but don't auto-hire her. */- E_CreateEmployee(EMPL_SCIENTIST, nation, NULL);- new_scientists++;- }+ totalIncome += funding; -- if (nation->stats[0].happiness > 0) {- for (j = 0; 0.25 + j < (float) nation->maxSoldiers * nation->stats[0].happiness * nation->stats[0].happiness * nation->stats[0].happiness; j++) {- /* Create a soldier. */- E_CreateEmployee(EMPL_SOLDIER, nation, NULL);- new_soldiers++;- }- }-- for (j = 0; 0.25 + j * 2 < (float) nation->maxSoldiers * nation->stats[0].happiness; j++) {- /* Create a worker. */- E_CreateEmployee(EMPL_WORKER, nation, NULL);- new_workers++;- }-- Com_sprintf(message, sizeof(message), _("Gained %i %s, %i %s, %i %s, and %i %s from nation %s (%s)"),+ if (funding > 0)+ strncat(mailBuffer, va(_("\t%s (%s)\t\t\t\t%i %s\t\t(%s%i %s)\n"),+ _(nation->name), NAT_GetHappinessString(nation), funding, ngettext("credit", "credits", funding),- new_scientists, ngettext("scientist", "scientists", new_scientists),- new_soldiers, ngettext("soldier", "soldiers", new_soldiers),- new_workers, ngettext("worker", "workers", new_workers),- _(nation->name), NAT_GetHappinessString(nation));- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ (funding >= lastFunding) ? "+" : "", (funding - lastFunding), ngettext("credit", "credits", (funding - lastFunding))), lengthof(mailBuffer)); }+ strncat(mailBuffer, va(_("^BTotal:\t\t\t\t\t%i %s\n"), totalIncome, ngettext("credit", "credits", totalIncome)), lengthof(mailBuffer)); ++ /* Expenses */+ strncat(mailBuffer, _("\n^BExpenses\n"), lengthof(mailBuffer)); cost = 0; for (i = 0; i < ccs.numEmployees[EMPL_SOLDIER]; i++) { if (ccs.employees[EMPL_SOLDIER][i].hired) cost += SALARY_SOLDIER_BASE + ccs.employees[EMPL_SOLDIER][i].chr.score.rank * SALARY_SOLDIER_RANKBONUS; }+ totalExpenditure += cost; - Com_sprintf(message, sizeof(message), _("Paid %i credits to soldiers"), cost);- CL_UpdateCredits(ccs.credits - cost);- /* only this message is played with sound as previous are added for every nation */- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qtrue);+ if (cost)+ strncat(mailBuffer, va(_("\tSoldiers' salary\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); cost = 0; for (i = 0; i < ccs.numEmployees[EMPL_WORKER]; i++) { if (ccs.employees[EMPL_WORKER][i].hired) cost += SALARY_WORKER_BASE + ccs.employees[EMPL_WORKER][i].chr.score.rank * SALARY_WORKER_RANKBONUS; }+ totalExpenditure += cost; - Com_sprintf(message, sizeof(message), _("Paid %i credits to workers"), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ if (cost)+ strncat(mailBuffer, va(_("\tWorkers' salary\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); cost = 0; for (i = 0; i < ccs.numEmployees[EMPL_SCIENTIST]; i++) { if (ccs.employees[EMPL_SCIENTIST][i].hired) cost += SALARY_SCIENTIST_BASE + ccs.employees[EMPL_SCIENTIST][i].chr.score.rank * SALARY_SCIENTIST_RANKBONUS; }+ totalExpenditure += cost; - Com_sprintf(message, sizeof(message), _("Paid %i credits to scientists"), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ if (cost)+ strncat(mailBuffer, va(_("\tScientists' salary\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); cost = 0; for (i = 0; i < ccs.numEmployees[EMPL_PILOT]; i++) { if (ccs.employees[EMPL_PILOT][i].hired) cost += SALARY_PILOT_BASE + ccs.employees[EMPL_PILOT][i].chr.score.rank * SALARY_PILOT_RANKBONUS; }+ totalExpenditure += cost; - Com_sprintf(message, sizeof(message), _("Paid %i credits to pilots"), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ if (cost)+ strncat(mailBuffer, va(_("\tPilots' salary\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); cost = 0; for (i = 0; i < ccs.numEmployees[EMPL_ROBOT]; i++) { if (ccs.employees[EMPL_ROBOT][i].hired) cost += SALARY_ROBOT_BASE + ccs.employees[EMPL_ROBOT][i].chr.score.rank * SALARY_ROBOT_RANKBONUS; }+ totalExpenditure += cost; - if (cost != 0) {- Com_sprintf(message, sizeof(message), _("Paid %i credits for robots"), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ if (cost) {+ strncat(mailBuffer, va(_("\tRobots maintenance cost\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); } cost = 0;@@ -147,11 +138,10 @@ cost += base->aircraft[j].price * SALARY_AIRCRAFT_FACTOR / SALARY_AIRCRAFT_DIVISOR; } }+ totalExpenditure += cost; - if (cost != 0) {- Com_sprintf(message, sizeof(message), _("Paid %i credits for aircraft"), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ if (cost) {+ strncat(mailBuffer, va(_("\tAircraft maintenance cost\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); } for (i = 0; i < MAX_BASES; i++) {@@ -162,26 +152,87 @@ for (j = 0; j < ccs.numBuildings[i]; j++) { cost += ccs.buildings[i][j].varCosts; }+ totalExpenditure += cost; - Com_sprintf(message, sizeof(message), _("Paid %i credits for upkeep of base %s"), cost, base->name);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);- CL_UpdateCredits(ccs.credits - cost);+ strncat(mailBuffer, va(_("\tUpkeep cost of base %s\t\t\t\t%i %s\n"), base->name, cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer)); } cost = SALARY_ADMIN_INITIAL + ccs.numEmployees[EMPL_SOLDIER] * SALARY_ADMIN_SOLDIER + ccs.numEmployees[EMPL_WORKER] * SALARY_ADMIN_WORKER + ccs.numEmployees[EMPL_SCIENTIST] * SALARY_ADMIN_SCIENTIST + ccs.numEmployees[EMPL_PILOT] * SALARY_ADMIN_PILOT + ccs.numEmployees[EMPL_ROBOT] * SALARY_ADMIN_ROBOT;- Com_sprintf(message, sizeof(message), _("Paid %i credits for administrative overhead."), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse); - if (initial_credits < 0) {- float interest = initial_credits * SALARY_DEBT_INTEREST;+ totalExpenditure += cost; + if (cost)+ strncat(mailBuffer, va(_("\tAdministrative costs\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer));++ if (initialCredits < 0) {+ float interest = initialCredits * SALARY_DEBT_INTEREST;+ cost = (int)ceil(interest);- Com_sprintf(message, sizeof(message), _("Paid %i credits in interest on your debt."), cost);- CL_UpdateCredits(ccs.credits - cost);- MS_AddNewMessageSound(_("Notice"), message, qfalse, MSG_STANDARD, NULL, qfalse);+ strncat(mailBuffer, va(_("\tInterest on your debt\t\t\t\t%i %s\n"), cost, ngettext("credit", "credits", cost)), lengthof(mailBuffer));+ totalExpenditure += cost; }- CL_GameTimeStop();+ CL_UpdateCredits(ccs.credits - totalExpenditure + totalIncome);++ strncat(mailBuffer, va(_("^BTotal:\t\t\t\t\t%i %s\n"), totalExpenditure, ngettext("credit", "credits", totalExpenditure)), lengthof(mailBuffer));++ strncat(mailBuffer, va(_("\n^BOveral change:\t\t\t\t\t%s%i %s\n"), (ccs.credits >= initialCredits) ? "+" : "", (ccs.credits - initialCredits), ngettext("credit", "credits", ccs.credits - initialCredits)), lengthof(mailBuffer));++ /* Personel */+ strncat(mailBuffer, _("\n^BNew personel\n"), lengthof(mailBuffer));+ for (i = 0; i < ccs.numNations; i++) {+ nation_t *nation = &ccs.nations[i];+ int new_scientists = 0;+ int new_soldiers = 0;+ int new_workers = 0;++ for (j = 0; 0.25 + j < (float) nation->maxScientists * nation->stats[0].happiness * nation->stats[0].happiness; j++) {+ /* Create a scientist, but don't auto-hire her. */+ E_CreateEmployee(EMPL_SCIENTIST, nation, NULL);+ new_scientists++;+ }++ if (nation->stats[0].happiness > 0) {+ for (j = 0; 0.25 + j < (float) nation->maxSoldiers * nation->stats[0].happiness * nation->stats[0].happiness * nation->stats[0].happiness; j++) {+ /* Create a soldier. */+ E_CreateEmployee(EMPL_SOLDIER, nation, NULL);+ new_soldiers++;+ }+ }++ for (j = 0; 0.25 + j * 2 < (float) nation->maxSoldiers * nation->stats[0].happiness; j++) {+ /* Create a worker. */+ E_CreateEmployee(EMPL_WORKER, nation, NULL);+ new_workers++;+ }++ if (new_soldiers || new_scientists || new_workers) {+ strncat(mailBuffer, va("\t%s (%s)\t\t\t", + _(nation->name), NAT_GetHappinessString(nation)), lengthof(mailBuffer));+ if (new_soldiers)+ strncat(mailBuffer, va("\t%s: %i", ngettext("soldier", "soldiers", new_soldiers),+ new_soldiers), lengthof(mailBuffer));+ if (new_scientists)+ strncat(mailBuffer, va("\t%s: %i", ngettext("scientist", "scientists", new_scientists),+ new_scientists), lengthof(mailBuffer));+ if (new_workers)+ strncat(mailBuffer, va("\t%s: %i", ngettext("worker", "workers", new_workers),+ new_workers), lengthof(mailBuffer));+ strncat(mailBuffer, "\n", lengthof(mailBuffer));+ }+ }++ /* don't free the old mail body here - it's the string of the source mail */+ mail->body = Mem_PoolStrDup(mailBuffer, cp_campaignPool, 0);++ /* update subject */+ /* Insert name of the mission in the template */+ CL_DateConvertLong(&ccs.date, &date);+ mail->subject = Mem_PoolStrDup(va(_(mail->subject), date.year, Date_GetMonthName(date.month - 2)), cp_campaignPool, 0);++ /* Add the mail to unread mail */+ Cmd_ExecuteString(va("addeventmail %s", mail->id));++/* CL_GameTimeStop();*/ } /**Index: base/ufos/events.ufo===================================================================--- base/ufos/events.ufo (revision 24881)+++ base/ufos/events.ufo (working copy)@@ -357,3 +357,13 @@ model "characters/al_kuhar" icon icons/air }++mail monthly_financial_report+{+ to "_mail_to_base_commander"+ from "_mail_from_paul_navarre"+ subject "_Monthly Financial Report: %i %s"+ notifytype "monthly_report"+ model "characters/navarre"+ icon icons/intelligence+}Index: base/ufos/msgcategories.ufo===================================================================--- base/ufos/msgcategories.ufo (revision 24881)+++ base/ufos/msgcategories.ufo (working copy)@@ -4,6 +4,10 @@ // Description: // definitions of categories to group notification types // the order of categories in this file defines the order in settings menu+msgcategory "_general"+{+ monthly_report+} msgcategory "_install_equipment" { installation_installed