1 | /* |
1 | /* |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
3 | * |
3 | * |
4 | * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify |
8 | * Deliantra is free software: you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License as published by |
… | |
… | |
126 | { |
126 | { |
127 | if (tmp->arch != NULL) |
127 | if (tmp->arch != NULL) |
128 | { |
128 | { |
129 | if (flag == F_BUY) |
129 | if (flag == F_BUY) |
130 | { |
130 | { |
131 | LOG (llevError, "Asking for buy-value of unidentified object.\n"); |
131 | LOG (llevError | logBacktrace, "Asking for buy-value of unidentified object.\n"); |
132 | val = tmp->arch->value * 50 * number; |
132 | val = tmp->arch->value * 50 * number; |
133 | } |
133 | } |
134 | else |
134 | else |
135 | { /* Trying to sell something, or get true value */ |
135 | { /* Trying to sell something, or get true value */ |
136 | if (tmp->type == POTION) |
136 | if (tmp->type == POTION) |
… | |
… | |
150 | else |
150 | else |
151 | { /* No archetype with this object */ |
151 | { /* No archetype with this object */ |
152 | LOG (llevDebug, "In sell item: Have object with no archetype: %s\n", &tmp->name); |
152 | LOG (llevDebug, "In sell item: Have object with no archetype: %s\n", &tmp->name); |
153 | if (flag == F_BUY) |
153 | if (flag == F_BUY) |
154 | { |
154 | { |
155 | LOG (llevError, "Asking for buy-value of unidentified object without arch.\n"); |
155 | LOG (llevError | logBacktrace, "Asking for buy-value of unidentified object without arch.\n"); |
156 | val = number * tmp->value * 10; |
156 | val = number * tmp->value * 10; |
157 | } |
157 | } |
158 | else |
158 | else |
159 | val = number * tmp->value / 5; |
159 | val = number * tmp->value / 5; |
160 | } |
160 | } |
… | |
… | |
206 | * AND Cha = 30 will get optimal price. |
206 | * AND Cha = 30 will get optimal price. |
207 | * Thus charisma will never get useless. |
207 | * Thus charisma will never get useless. |
208 | * -b.e. edler@heydernet.de |
208 | * -b.e. edler@heydernet.de |
209 | */ |
209 | */ |
210 | |
210 | |
211 | if (who != NULL && who->type == PLAYER) |
211 | if (who && who->type == PLAYER) |
212 | { |
212 | { |
213 | int lev_bargain = 0; |
213 | int lev_bargain = 0; |
214 | int lev_identify = 0; |
214 | int lev_identify = 0; |
215 | int idskill1 = 0; |
|
|
216 | int idskill2 = 0; |
|
|
217 | const typedata *tmptype; |
|
|
218 | |
|
|
219 | tmptype = get_typedata (tmp->type); |
|
|
220 | |
215 | |
221 | if (find_skill_by_number (who, SK_BARGAINING)) |
216 | if (find_skill_by_number (who, SK_BARGAINING)) |
222 | lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level; |
217 | lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level; |
223 | |
218 | |
224 | if (tmptype) |
219 | if (const typedata *tmptype = get_typedata (tmp->type)) |
225 | { |
220 | { |
226 | idskill1 = tmptype->identifyskill; |
221 | if (int idskill1 = tmptype->identifyskill) |
227 | |
|
|
228 | if (idskill1) |
|
|
229 | { |
222 | { |
230 | idskill2 = tmptype->identifyskill2; |
223 | int idskill2 = tmptype->identifyskill2; |
231 | |
224 | |
232 | if (find_skill_by_number (who, idskill1)) |
225 | if (find_skill_by_number (who, idskill1)) |
233 | lev_identify = find_skill_by_number (who, idskill1)->level; |
226 | lev_identify = find_skill_by_number (who, idskill1)->level; |
234 | |
227 | |
235 | if (idskill2 && find_skill_by_number (who, idskill2)) |
228 | if (idskill2 && find_skill_by_number (who, idskill2)) |
236 | lev_identify += find_skill_by_number (who, idskill2)->level; |
229 | lev_identify += find_skill_by_number (who, idskill2)->level; |
237 | } |
230 | } |
238 | } |
231 | } |
239 | else |
|
|
240 | LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->debug_desc ()); |
|
|
241 | |
232 | |
242 | /* ratio determines how much of the price modification |
233 | /* ratio determines how much of the price modification |
243 | * will come from the basic stat charisma |
234 | * will come from the basic stat charisma |
244 | * the rest will come from the level in bargaining skill |
235 | * the rest will come from the level in bargaining skill |
245 | */ |
236 | */ |
… | |
… | |
418 | |
409 | |
419 | if (coin == NULL) |
410 | if (coin == NULL) |
420 | return "nothing"; |
411 | return "nothing"; |
421 | |
412 | |
422 | num = real_value / coin->value; |
413 | num = real_value / coin->value; |
|
|
414 | |
423 | if (num == 1) |
415 | if (num == 1) |
424 | sprintf (buf, "about one %s", &coin->object::name); |
416 | sprintf (buf, "about one %s", &coin->object::name); |
425 | else if (num < 5) |
417 | else if (num < 5) |
426 | sprintf (buf, "a few %s", &coin->object::name_pl); |
418 | sprintf (buf, "a few %s", &coin->object::name_pl); |
427 | else if (num < 10) |
419 | else if (num < 10) |
… | |
… | |
432 | sprintf (buf, "lots of %s", &coin->object::name_pl); |
424 | sprintf (buf, "lots of %s", &coin->object::name_pl); |
433 | else if (num < 1000) |
425 | else if (num < 1000) |
434 | sprintf (buf, "a great many %s", &coin->object::name_pl); |
426 | sprintf (buf, "a great many %s", &coin->object::name_pl); |
435 | else |
427 | else |
436 | sprintf (buf, "a vast quantity of %s", &coin->object::name_pl); |
428 | sprintf (buf, "a vast quantity of %s", &coin->object::name_pl); |
|
|
429 | |
437 | return buf; |
430 | return buf; |
438 | } |
431 | } |
439 | } |
432 | } |
440 | } |
433 | } |
441 | |
434 | |
… | |
… | |
583 | { |
576 | { |
584 | // This should not happen, but if it does, just merge the two. |
577 | // This should not happen, but if it does, just merge the two. |
585 | if (coin_objs [i]) |
578 | if (coin_objs [i]) |
586 | { |
579 | { |
587 | LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]); |
580 | LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]); |
588 | tmp->remove (); |
|
|
589 | coin_objs[i]->nrof += tmp->nrof; |
581 | coin_objs[i]->nrof += tmp->nrof; |
590 | esrv_del_item (pl->contr, tmp->count); |
|
|
591 | tmp->destroy (); |
582 | tmp->destroy (true); |
592 | } |
583 | } |
593 | else |
584 | else |
594 | { |
585 | { |
595 | tmp->remove (); |
586 | tmp->remove (); |
596 | |
|
|
597 | if (pouch->type == PLAYER) |
|
|
598 | esrv_del_item (pl->contr, tmp->count); |
|
|
599 | |
|
|
600 | coin_objs[i] = tmp; |
587 | coin_objs[i] = tmp; |
601 | } |
588 | } |
602 | |
589 | |
603 | break; |
590 | break; |
604 | } |
591 | } |
… | |
… | |
644 | count--; |
631 | count--; |
645 | } |
632 | } |
646 | } |
633 | } |
647 | |
634 | |
648 | for (i = 0; i < NUM_COINS; i++) |
635 | for (i = 0; i < NUM_COINS; i++) |
649 | { |
|
|
650 | if (coin_objs[i]->nrof) |
636 | if (coin_objs[i]->nrof) |
651 | { |
|
|
652 | object *tmp = insert_ob_in_ob (coin_objs[i], pouch); |
637 | insert_ob_in_ob (coin_objs [i], pouch); |
653 | |
|
|
654 | esrv_send_item (pl, tmp); |
|
|
655 | esrv_send_item (pl, pouch); |
|
|
656 | |
|
|
657 | if (pl != pouch) |
|
|
658 | esrv_update_item (UPD_WEIGHT, pl, pouch); |
|
|
659 | |
|
|
660 | if (pl->type != PLAYER) |
|
|
661 | esrv_send_item (pl, pl); |
|
|
662 | } |
|
|
663 | else |
638 | else |
664 | coin_objs[i]->destroy (); |
639 | coin_objs[i]->destroy (true); |
665 | } |
|
|
666 | } |
640 | } |
667 | |
641 | |
668 | /* Checks all unpaid items in op's inventory, adds up all the money they |
642 | /* Checks all unpaid items in op's inventory, adds up all the money they |
669 | * have, and checks that they can actually afford what they want to buy. |
643 | * have, and checks that they can actually afford what they want to buy. |
670 | * Returns 1 if they can, and 0 if they can't. also prints an appropriate message |
644 | * Returns 1 if they can, and 0 if they can't. also prints an appropriate message |
… | |
… | |
690 | unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); |
664 | unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); |
691 | } |
665 | } |
692 | |
666 | |
693 | if (unpaid_price > player_wealth) |
667 | if (unpaid_price > player_wealth) |
694 | { |
668 | { |
695 | char buf[MAX_BUF]; |
669 | dynbuf_text buf; |
696 | char cost[MAX_BUF]; |
|
|
697 | char missing[MAX_BUF]; |
|
|
698 | |
670 | |
699 | snprintf (cost, MAX_BUF, "%s", cost_string_from_value (unpaid_price, 0)); |
671 | buf << "You have " << unpaid_count |
700 | snprintf (missing, MAX_BUF, "%s", cost_string_from_value (unpaid_price - player_wealth, 0)); |
672 | << " unpaid item(s) that would cost you " << cost_string_from_value (unpaid_price, 0) |
|
|
673 | << ". You need another " << cost_string_from_value (unpaid_price - player_wealth, 0) |
|
|
674 | << " to be able to afford that."; |
701 | |
675 | |
702 | snprintf (buf, MAX_BUF, "You have %d unpaid items that would cost you %s. You need another %s to be able to afford that.", |
676 | pl->failmsg (buf); |
703 | unpaid_count, cost, missing); |
|
|
704 | new_draw_info (NDI_UNIQUE, 0, pl, buf); |
|
|
705 | |
677 | |
706 | return 0; |
678 | return 0; |
707 | } |
679 | } |
708 | else |
680 | else |
709 | return 1; |
681 | return 1; |
… | |
… | |
738 | SET_FLAG (op, FLAG_UNPAID); |
710 | SET_FLAG (op, FLAG_UNPAID); |
739 | return 0; |
711 | return 0; |
740 | } |
712 | } |
741 | else |
713 | else |
742 | { |
714 | { |
743 | object *tmp; |
|
|
744 | |
|
|
745 | CLEAR_FLAG (op, FLAG_UNPAID); |
715 | CLEAR_FLAG (op, FLAG_UNPAID); |
746 | CLEAR_FLAG (op, FLAG_PLAYER_SOLD); |
716 | CLEAR_FLAG (op, FLAG_PLAYER_SOLD); |
747 | new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op)); |
717 | new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op)); |
748 | tmp = merge_ob (op, NULL); |
|
|
749 | |
718 | |
750 | if (pl->type == PLAYER) |
719 | if (!merge_ob (op, op->env->inv)) |
751 | { |
|
|
752 | if (tmp) |
|
|
753 | { /* it was merged */ |
|
|
754 | esrv_del_item (pl->contr, op->count); |
|
|
755 | op = tmp; |
|
|
756 | } |
|
|
757 | |
|
|
758 | esrv_send_item (pl, op); |
720 | esrv_update_item (UPD_FLAGS, pl, op); |
759 | } |
|
|
760 | |
721 | |
761 | goto next_item; |
722 | goto next_item; |
762 | } |
723 | } |
763 | } |
724 | } |
764 | } |
725 | } |
… | |
… | |
806 | if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit)) |
767 | if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit)) |
807 | { |
768 | { |
808 | if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n) |
769 | if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n) |
809 | n = (pouch->weight_limit - pouch->carrying) / w; |
770 | n = (pouch->weight_limit - pouch->carrying) / w; |
810 | |
771 | |
811 | tmp = arch_to_object (at); |
772 | object *tmp = arch_to_object (at); |
812 | tmp->nrof = n; |
773 | tmp->nrof = n; |
813 | amount -= tmp->nrof * tmp->value; |
774 | amount -= tmp->nrof * tmp->value; |
814 | tmp = insert_ob_in_ob (tmp, pouch); |
775 | pouch->insert (tmp); |
815 | esrv_send_item (pl, tmp); |
|
|
816 | esrv_send_item (pl, pouch); |
|
|
817 | esrv_update_item (UPD_WEIGHT, pl, pouch); |
|
|
818 | esrv_send_item (pl, pl); |
|
|
819 | } |
776 | } |
820 | } |
777 | } |
821 | } |
778 | } |
822 | |
779 | |
823 | if (amount / at->value > 0) |
780 | if (amount / at->value > 0) |
824 | { |
781 | { |
825 | tmp = arch_to_object (at); |
782 | object *tmp = arch_to_object (at); |
826 | tmp->nrof = amount / tmp->value; |
783 | tmp->nrof = amount / tmp->value; |
827 | amount -= tmp->nrof * tmp->value; |
784 | amount -= tmp->nrof * tmp->value; |
828 | tmp = insert_ob_in_ob (tmp, pl); |
785 | pl->insert (tmp); |
829 | esrv_send_item (pl, tmp); |
|
|
830 | esrv_send_item (pl, pl); |
|
|
831 | } |
786 | } |
832 | } |
787 | } |
833 | } |
788 | } |
834 | |
789 | |
835 | if (amount != 0) |
790 | if (amount != 0) |
… | |
… | |
838 | |
793 | |
839 | /* elmex: this is for the bank plugin :( */ |
794 | /* elmex: this is for the bank plugin :( */ |
840 | sint64 |
795 | sint64 |
841 | pay_player_arch (object *pl, const char *arch, sint64 amount) |
796 | pay_player_arch (object *pl, const char *arch, sint64 amount) |
842 | { |
797 | { |
843 | archetype *at = archetype::find (arch); |
|
|
844 | object *tmp = NULL; |
|
|
845 | |
|
|
846 | if (at == NULL) |
|
|
847 | return 0; |
|
|
848 | |
|
|
849 | if (amount > 0) |
798 | if (amount) |
850 | { |
799 | { |
851 | tmp = arch_to_object (at); |
800 | object *ob = archetype::get (arch); |
|
|
801 | |
|
|
802 | if (!ob) |
|
|
803 | return 0; |
|
|
804 | |
852 | tmp->nrof = amount; |
805 | ob->nrof = amount; |
853 | tmp = insert_ob_in_ob (tmp, pl); |
806 | pl->insert (ob); |
854 | esrv_send_item (pl, tmp); |
|
|
855 | esrv_send_item (pl, pl); |
|
|
856 | } |
807 | } |
857 | |
808 | |
858 | return 1; |
809 | return 1; |
859 | } |
810 | } |
860 | |
811 | |
… | |
… | |
863 | * buy item. |
814 | * buy item. |
864 | * |
815 | * |
865 | * Modified to fill available race: gold containers before dumping |
816 | * Modified to fill available race: gold containers before dumping |
866 | * remaining coins in character's inventory. |
817 | * remaining coins in character's inventory. |
867 | */ |
818 | */ |
868 | void |
819 | bool |
869 | sell_item (object *op, object *pl) |
820 | sell_item (object *op, object *pl) |
870 | { |
821 | { |
871 | sint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain; |
822 | sint64 amount = query_cost (op, pl, F_SELL | F_SHOP), extra_gain; |
872 | |
823 | |
873 | if (pl == NULL || pl->type != PLAYER) |
824 | if (pl == NULL || pl->type != PLAYER) |
874 | { |
825 | { |
875 | LOG (llevDebug, "Object other than player tried to sell something.\n"); |
826 | LOG (llevDebug, "Object other than player tried to sell something.\n"); |
876 | return; |
827 | return false; |
877 | } |
828 | } |
878 | |
829 | |
879 | op->custom_name = 0; |
830 | op->custom_name = 0; |
880 | |
831 | |
881 | if (!amount) |
832 | if (!amount) |
882 | { |
833 | { |
883 | new_draw_info_format (NDI_UNIQUE, 0, pl, "We're not interested in %s.", query_name (op)); |
834 | new_draw_info_format (NDI_UNIQUE, 0, pl, "We're not interested in %s.", |
884 | |
835 | query_name (op)); |
885 | /* Even if the character doesn't get anything for it, it may still be |
836 | // elmex: change: the player now gets the item back if the shop is not |
886 | * worth something. If so, make it unpaid |
837 | // interested in it. |
887 | */ |
|
|
888 | if (op->value) |
|
|
889 | { |
|
|
890 | SET_FLAG (op, FLAG_UNPAID); |
|
|
891 | SET_FLAG (op, FLAG_PLAYER_SOLD); |
|
|
892 | } |
|
|
893 | |
|
|
894 | identify (op); |
|
|
895 | return; |
838 | return false; |
896 | } |
839 | } |
897 | |
840 | |
898 | /* We compare the price with the one for a player |
841 | /* We compare the price with the one for a player |
899 | * without bargaining skill. |
842 | * without bargaining skill. |
900 | * This determins the amount of exp (if any) gained for bargaining. |
843 | * This determins the amount of exp (if any) gained for bargaining. |
… | |
… | |
905 | if (extra_gain > 0) |
848 | if (extra_gain > 0) |
906 | change_exp (pl, extra_gain / 10, "bargaining", SK_EXP_NONE); |
849 | change_exp (pl, extra_gain / 10, "bargaining", SK_EXP_NONE); |
907 | |
850 | |
908 | pay_player (pl, amount); |
851 | pay_player (pl, amount); |
909 | |
852 | |
910 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.", query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op)); |
853 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You receive %s for %s.", |
|
|
854 | query_cost_string (op, pl, F_SELL | F_SHOP), query_name (op)); |
911 | pl->play_sound (sound_find ("shop_sell")); |
855 | pl->play_sound (sound_find ("shop_sell")); |
912 | |
856 | |
913 | SET_FLAG (op, FLAG_UNPAID); |
857 | SET_FLAG (op, FLAG_UNPAID); |
914 | identify (op); |
858 | identify (op); |
|
|
859 | |
|
|
860 | return true; |
915 | } |
861 | } |
916 | |
862 | |
917 | /* returns a double that is the ratio of the price that a shop will offer for |
863 | /* returns a double that is the ratio of the price that a shop will offer for |
918 | * item based on the shops specialisation. Does not take account of greed, |
864 | * item based on the shops specialisation. Does not take account of greed, |
919 | * returned value is between SPECIALISATION_EFFECT and 1. |
865 | * returned value is between SPECIALISATION_EFFECT and 1. |
… | |
… | |
1117 | { |
1063 | { |
1118 | shopinv *s1 = (shopinv *) a1, *s2 = (shopinv *) a2; |
1064 | shopinv *s1 = (shopinv *) a1, *s2 = (shopinv *) a2; |
1119 | |
1065 | |
1120 | if (s1->type < s2->type) |
1066 | if (s1->type < s2->type) |
1121 | return -1; |
1067 | return -1; |
|
|
1068 | |
1122 | if (s1->type > s2->type) |
1069 | if (s1->type > s2->type) |
1123 | return 1; |
1070 | return 1; |
1124 | |
1071 | |
1125 | /* the type is the same (what atoi gets), so do a strcasecmp to sort |
1072 | /* the type is the same (what atoi gets), so do a strcasecmp to sort |
1126 | * via alphabetical order |
1073 | * via alphabetical order |
… | |
… | |
1176 | |
1123 | |
1177 | void |
1124 | void |
1178 | shop_listing (object *sign, object *op) |
1125 | shop_listing (object *sign, object *op) |
1179 | { |
1126 | { |
1180 | int i, j, numitems = 0, numallocated = 0, x1, x2, y1, y2; |
1127 | int i, j, numitems = 0, numallocated = 0, x1, x2, y1, y2; |
1181 | const char *shop_coords = get_ob_key_value (sign, "shop_coords"); |
1128 | const char *shop_coords = sign->kv (shstr_shop_coords); |
1182 | object *stack; |
1129 | object *stack; |
1183 | shopinv *items; |
1130 | shopinv *items; |
1184 | |
1131 | |
1185 | /* Should never happen, but just in case a monster does apply a sign */ |
1132 | /* Should never happen, but just in case a monster does apply a sign */ |
1186 | if (op->type != PLAYER) |
1133 | if (op->type != PLAYER) |
… | |
… | |
1259 | |
1206 | |
1260 | /* elmex: this function checks whether the object is in a shop */ |
1207 | /* elmex: this function checks whether the object is in a shop */ |
1261 | bool |
1208 | bool |
1262 | is_in_shop (object *o) |
1209 | is_in_shop (object *o) |
1263 | { |
1210 | { |
1264 | if (!o->map) |
1211 | if (!o->is_on_map ()) |
1265 | return false; |
1212 | return false; |
1266 | |
1213 | |
1267 | return is_in_shop (o->map, o->x, o->y); |
1214 | return is_in_shop (o->map, o->x, o->y); |
1268 | } |
1215 | } |
1269 | |
1216 | |
… | |
… | |
1277 | is_in_shop (maptile *map, int x, int y) |
1224 | is_in_shop (maptile *map, int x, int y) |
1278 | { |
1225 | { |
1279 | for (object *floor = GET_MAP_OB (map, x, y); floor; floor = floor->above) |
1226 | for (object *floor = GET_MAP_OB (map, x, y); floor; floor = floor->above) |
1280 | if (QUERY_FLAG (floor, FLAG_IS_FLOOR)) |
1227 | if (QUERY_FLAG (floor, FLAG_IS_FLOOR)) |
1281 | return floor->type == SHOP_FLOOR; |
1228 | return floor->type == SHOP_FLOOR; |
|
|
1229 | |
1282 | return false; |
1230 | return false; |
1283 | } |
1231 | } |
1284 | |
1232 | |