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,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 Frank Tore Johansen |
6 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * the terms of the Affero GNU General Public License as published by the |
9 | * the terms of the Affero GNU General Public License as published by the |
… | |
… | |
649 | return 100; |
649 | return 100; |
650 | |
650 | |
651 | return rv; |
651 | return rv; |
652 | } |
652 | } |
653 | |
653 | |
|
|
654 | static int |
|
|
655 | cmp_skillp (const void *sk1, const void *sk2) |
|
|
656 | { |
|
|
657 | return strcmp (&((*(const object **) sk1)->name), |
|
|
658 | &((*(const object **) sk2)->name)); |
|
|
659 | } |
|
|
660 | |
654 | /* show_skills() - Meant to allow players to examine |
661 | /* show_skills() - Meant to allow players to examine |
655 | * their current skill list. |
662 | * their current skill list. |
656 | * This shows the amount of exp they have in the skills. |
663 | * This shows the amount of exp they have in the skills. |
657 | * we also include some other non skill related info (god, |
664 | * we also include some other non skill related info (god, |
658 | * max weapon improvments, item power). |
665 | * max weapon improvments, item power). |
659 | * Note this function is a bit more complicated becauase we |
666 | * Note this function is a bit more complicated becauase we |
660 | * we want ot sort the skills before printing them. If we |
667 | * we want ot sort the skills before printing them. If we |
661 | * just dumped this as we found it, this would be a bit |
668 | * just dumped this as we found it, this would be a bit |
662 | * simpler. |
669 | * simpler. |
663 | */ |
670 | */ |
664 | //TODO: egad, do it in perl, do not suffer from the big buffer on stack, make it one single drawinfo. |
|
|
665 | void |
671 | void |
666 | show_skills (object *pl, const char *search) |
672 | show_skills (object *pl, const char *search) |
667 | { |
673 | { |
668 | const char *cp; |
674 | const char *cp; |
669 | int i, num_skills_found = 0; |
675 | int i, num_skills_found = 0; |
670 | const char *const periods = ".............................."; // 30 |
676 | object *skills[CS_NUM_SKILLS]; |
671 | |
|
|
672 | /* Need to have a pointer and use strdup for qsort to work properly */ |
|
|
673 | char skills[NUM_SKILLS][128]; // d'oh |
|
|
674 | |
|
|
675 | object *op = pl->contr->ob; |
677 | object *op = pl->contr->ob; |
676 | |
678 | |
|
|
679 | /* find the skills */ |
677 | for (object *tmp = op->inv; tmp; tmp = tmp->below) |
680 | for (object *tmp = op->inv; tmp; tmp = tmp->below) |
678 | { |
681 | { |
679 | if (tmp->type == SKILL) |
682 | if (tmp->type == SKILL) |
680 | { |
683 | { |
681 | if (search && !tmp->name.contains (search)) |
684 | if (search && !tmp->name.contains (search)) |
682 | continue; |
685 | continue; |
683 | |
686 | |
684 | char buf[30]; |
687 | skills[num_skills_found++] = tmp; |
685 | |
|
|
686 | /* Basically want to fill this out to 30 spaces with periods */ |
|
|
687 | snprintf (buf, sizeof (buf), "%s%s", &tmp->name, periods); |
|
|
688 | |
|
|
689 | if (settings.permanent_exp_ratio) |
|
|
690 | snprintf (skills[num_skills_found++], sizeof (skills [0]), "%slvl:%3d (xp:%" PRId64 "/%" PRId64 "/%d%%)", |
|
|
691 | buf, tmp->level, tmp->stats.exp, |
|
|
692 | level_exp (tmp->level + 1, op->expmul), clipped_percent (tmp->perm_exp, tmp->stats.exp)); |
|
|
693 | else |
|
|
694 | snprintf (skills[num_skills_found++], sizeof (skills [0]), "%slvl:%3d (xp:%" PRId64 "/%" PRId64 ")", |
|
|
695 | buf, tmp->level, tmp->stats.exp, level_exp (tmp->level + 1, op->expmul)); |
|
|
696 | |
688 | |
697 | /* I don't know why some characters get a bunch of skills, but |
689 | /* I don't know why some characters get a bunch of skills, but |
698 | * it sometimes happens (maybe a leftover from bugier earlier code |
690 | * it sometimes happens (maybe a leftover from bugier earlier code |
699 | * and those character are still about). In any case, lets handle |
691 | * and those character are still about). In any case, lets handle |
700 | * it so it doesn't crash the server - otherwise, one character may |
692 | * it so it doesn't crash the server - otherwise, one character may |
701 | * crash the server numerous times. |
693 | * crash the server numerous times. |
702 | */ |
694 | */ |
703 | if (num_skills_found >= NUM_SKILLS) |
695 | if (num_skills_found >= CS_NUM_SKILLS) |
704 | { |
696 | { |
705 | new_draw_info (NDI_RED | NDI_REPLY, 0, op, "Your character has too many skills."); |
697 | new_draw_info (NDI_RED | NDI_REPLY, 0, op, "Your character has too many skills."); |
706 | new_draw_info (NDI_RED | NDI_REPLY, 0, op, "Something isn't right - contact the server admin"); |
698 | new_draw_info (NDI_RED | NDI_REPLY, 0, op, "Something isn't right - contact the server admin"); |
707 | break; |
699 | break; |
708 | } |
700 | } |
… | |
… | |
711 | |
703 | |
712 | dynbuf_text &msg = msg_dynbuf; msg.clear (); |
704 | dynbuf_text &msg = msg_dynbuf; msg.clear (); |
713 | |
705 | |
714 | msg << "T<Player skills:>\n\n"; |
706 | msg << "T<Player skills:>\n\n"; |
715 | if (num_skills_found > 1) |
707 | if (num_skills_found > 1) |
716 | qsort (skills, num_skills_found, sizeof (skills [0]), (int (*)(const void *, const void *)) std::strcmp); |
708 | qsort (skills, num_skills_found, sizeof (skills [0]), cmp_skillp); |
717 | |
709 | |
|
|
710 | char buf[31]; /* +1 for '\0' */ |
|
|
711 | const char *const periods = ".............................."; // 30 |
|
|
712 | |
718 | for (i = 0; i < num_skills_found; i++) |
713 | for (i = 0; i < num_skills_found; i++) { |
719 | msg << " C<" << skills [i] << ">\n"; |
714 | object *tmp = skills[i]; |
|
|
715 | |
|
|
716 | /* Basically want to fill this out to 30 spaces with periods */ |
|
|
717 | snprintf (buf, sizeof (buf), "%s%s", &tmp->name, periods); |
|
|
718 | |
|
|
719 | msg << " C<"; |
|
|
720 | |
|
|
721 | if (settings.permanent_exp_ratio) |
|
|
722 | msg.printf ("%slvl:%3d (xp:%" PRId64 "/%" PRId64 "/%d%%)", |
|
|
723 | buf, tmp->level, tmp->stats.exp, level_exp (tmp->level + 1, op->expmul), |
|
|
724 | clipped_percent (tmp->perm_exp, tmp->stats.exp)); |
|
|
725 | else |
|
|
726 | msg.printf ("%slvl:%3d (xp:%" PRId64 "/%" PRId64 ")", |
|
|
727 | buf, tmp->level, tmp->stats.exp, level_exp (tmp->level + 1, op->expmul)); |
|
|
728 | |
|
|
729 | msg << ">\n"; |
|
|
730 | } |
720 | |
731 | |
721 | msg << "\nYou can handle " << op->level / 5 + 5 << " weapon improvements.\r"; |
732 | msg << "\nYou can handle " << op->level / 5 + 5 << " weapon improvements.\r"; |
722 | |
733 | |
723 | cp = determine_god (op); |
734 | cp = determine_god (op); |
724 | msg << "You worship " << (cp ? cp : "no god at current time") << ".\r"; |
735 | msg << "You worship " << (cp ? cp : "no god at current time") << ".\r"; |
… | |
… | |
888 | |
899 | |
889 | if (!op->apply (pl->combat_ob)) |
900 | if (!op->apply (pl->combat_ob)) |
890 | return 0; |
901 | return 0; |
891 | |
902 | |
892 | if (!op->chosen_skill) |
903 | if (!op->chosen_skill) |
|
|
904 | { |
893 | LOG (llevError, "do_skill_attack: weapon has no skill (%s)", pl->combat_ob->debug_desc ()); |
905 | LOG (llevError, "do_skill_attack: weapon has no skill (%s)", pl->combat_ob->debug_desc ()); |
|
|
906 | new_draw_info (NDI_RED | NDI_REPLY, 0, op, "You hit a bug in the server, please contact an admin!"); |
|
|
907 | return 0; |
|
|
908 | } |
894 | } |
909 | } |
895 | |
910 | |
896 | /* lose invisiblity/hiding status for running attacks */ |
911 | /* lose invisiblity/hiding status for running attacks */ |
897 | if (pl->tmp_invis) |
912 | if (pl->tmp_invis) |
898 | { |
913 | { |