Index: 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; else Index: 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