Atrinik Server 2.5
types/book.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00035 #define BOOK_LEVEL_DIFF 12
00036 
00042 static int book_level_mod[MAX_STAT + 1] =
00043 {
00044     -9,
00045     -8, -7, -6, -5, -4,
00046     -4, -3, -2, -2, -1,
00047     0, 0, 0, 0, 0,
00048     1, 1, 2, 2, 3,
00049     3, 3, 4, 4, 5,
00050     6, 7, 8, 9, 10
00051 };
00052 
00058 static double book_exp_mod[MAX_STAT + 1] =
00059 {
00060     -3.00f,
00061     -2.00f, -1.90f, -1.80f, -1.70f, -1.60f,
00062     -1.50f, -1.40f, -1.30f, -1.20f, -1.10f,
00063     1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
00064     1.05f, 1.10f, 1.15f, 1.20f, 1.30f,
00065     1.35f, 1.40f, 1.50f, 1.55f, 1.60f,
00066     1.70f, 1.75f, 1.85f, 1.90f, 2.00f
00067 };
00068 
00081 void apply_book(object *op, object *tmp)
00082 {
00083     int lev_diff;
00084     SockList sl;
00085     unsigned char sock_buf[MAXSOCKBUF];
00086 
00087     if (QUERY_FLAG(op, FLAG_BLIND) && !QUERY_FLAG(op,FLAG_WIZ))
00088     {
00089         new_draw_info(0, COLOR_WHITE, op, "You are unable to read while blind.");
00090         return;
00091     }
00092 
00093     if (tmp->msg == NULL)
00094     {
00095         new_draw_info_format(0, COLOR_WHITE, op, "You open the %s and find it empty.", tmp->name);
00096         return;
00097     }
00098 
00099     /* Need a literacy skill to read stuff! */
00100     if (!change_skill(op, SK_LITERACY))
00101     {
00102         new_draw_info(0, COLOR_WHITE, op, "You are unable to decipher the strange symbols.");
00103         return;
00104     }
00105 
00106     lev_diff = tmp->level - (SK_level(op) + BOOK_LEVEL_DIFF + book_level_mod[op->stats.Int]);
00107 
00108     if (!QUERY_FLAG(op, FLAG_WIZ) && lev_diff > 0)
00109     {
00110         if (lev_diff < 2)
00111         {
00112             new_draw_info(0, COLOR_WHITE, op, "This book is just barely beyond your comprehension.");
00113         }
00114         else if (lev_diff < 3)
00115         {
00116             new_draw_info(0, COLOR_WHITE, op, "This book is slightly beyond your comprehension.");
00117         }
00118         else if (lev_diff < 5)
00119         {
00120             new_draw_info(0, COLOR_WHITE, op, "This book is beyond your comprehension.");
00121         }
00122         else if (lev_diff < 8)
00123         {
00124             new_draw_info(0, COLOR_WHITE, op, "This book is quite a bit beyond your comprehension.");
00125         }
00126         else if (lev_diff < 15)
00127         {
00128             new_draw_info(0, COLOR_WHITE, op, "This book is way beyond your comprehension.");
00129         }
00130         else
00131         {
00132             new_draw_info(0, COLOR_WHITE, op, "This book is totally beyond your comprehension.");
00133         }
00134 
00135         return;
00136     }
00137 
00138     new_draw_info_format(0, COLOR_WHITE, op, "You open the %s and start reading.", tmp->name);
00139     CONTR(op)->stat_books_read++;
00140 
00141     sl.buf = sock_buf;
00142     SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_BOOK);
00143 
00144     SockList_AddStringUnterm(&sl, "<book>");
00145     SockList_AddStringUnterm(&sl, query_base_name(tmp, NULL));
00146     SockList_AddStringUnterm(&sl, "</book>");
00147     SockList_AddString(&sl, tmp->msg);
00148 
00149     Send_With_Handling(&CONTR(op)->socket, &sl);
00150 
00151     /* Gain xp from reading but only if not read before. */
00152     if (!QUERY_FLAG(tmp, FLAG_NO_SKILL_IDENT))
00153     {
00154         sint64 exp_gain, old_exp;
00155 
00156         CONTR(op)->stat_unique_books_read++;
00157 
00158         /* Store original exp value. We want to keep the experience cap
00159          * from calc_skill_exp() below, so we temporarily adjust the exp
00160          * of the book, instead of adjusting the return value. */
00161         old_exp = tmp->stats.exp;
00162         /* Adjust the experience based on player's wisdom. */
00163         tmp->stats.exp = (sint64) ((double) tmp->stats.exp * book_exp_mod[op->stats.Wis]);
00164 
00165         if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED))
00166         {
00167             /* Because they just identified it too. */
00168             tmp->stats.exp *= 1.5f;
00169             SET_FLAG(tmp, FLAG_IDENTIFIED);
00170 
00171             /* If in a container, update how it looks. */
00172             if (tmp->env)
00173             {
00174                 esrv_update_item(UPD_FLAGS | UPD_NAME, op, tmp);
00175             }
00176             else
00177             {
00178                 CONTR(op)->socket.update_tile = 0;
00179             }
00180         }
00181 
00182         exp_gain = calc_skill_exp(op, tmp, -1);
00183         add_exp(op, exp_gain, op->chosen_skill->stats.sp, 0);
00184 
00185         /* So no more exp gained from this book. */
00186         SET_FLAG(tmp, FLAG_NO_SKILL_IDENT);
00187         /* Restore old experience value. */
00188         tmp->stats.exp = old_exp;
00189     }
00190 }