1 #include "rpg.h"
2 
3 namespace game
4 {
5     vector<rpgobj *> objects, stack;
6     hashset<char *> names;
7 
8     rpgobj *pointingat = NULL;
9     rpgobj *playerobj = NULL;
10     rpgobj *selected = NULL;
11 
12     rpgquest *quests = NULL;
13     rpgquest *currentquest = NULL;
14 
resetstack()15     void resetstack()
16     {
17         stack.setsize(0);
18         loopi(10) stack.add(playerobj);     // determines the stack depth
19     }
20 
clearworld()21     void clearworld()
22     {
23         if(playerobj) { playerobj->ent = NULL; delete playerobj; }
24         playerobj = new rpgobj("player");
25         playerobj->ent = player1;
26         player1->ro = playerobj;
27 
28         pointingat = NULL;
29         objects.deletecontents();
30         resetstack();
31 
32         playerobj->scriptinit();            // will fail when this is called from emptymap(), which is ok
33     }
34 
removefromsystem(rpgobj * o)35     void removefromsystem(rpgobj *o)
36     {
37         removefromworld(o);
38         o->decontain();
39         if(pointingat==o) pointingat = NULL;
40         if(selected==o) selected = NULL;
41         resetstack();
42         DELETEP(o);
43     }
44 
updateobjects()45     void updateobjects()
46     {
47         pointingat = NULL;
48         loopv(objects)
49         {
50             objects[i]->update();
51 
52             float dist = player1->o.dist(objects[i]->ent->o);
53             if(dist<50 && intersect(objects[i]->ent, player1->o, worldpos) && (!pointingat || player1->o.dist(pointingat->ent->o)>dist))
54             {
55                 pointingat = objects[i];
56             }
57         }
58     }
59 
spawn(char * name)60     void spawn(char *name)
61     {
62         rpgobj *o = new rpgobj(name);
63         pushobj(o);
64         o->scriptinit();
65     }
66 
placeinworld(vec & pos,float yaw)67     void placeinworld(vec &pos, float yaw)
68     {
69         stack[0]->placedinworld(new rpgent(stack[0], pos, yaw));
70         objects.add(stack[0]);
71     }
72 
spawnfroment(rpgentity & e)73     void spawnfroment(rpgentity &e)
74     {
75         spawn(e.name);
76         placeinworld(e.o, e.attr1);
77     }
78 
pushobj(rpgobj * o)79     void pushobj(rpgobj *o) { stack.pop(); stack.insert(0, o); }       // never overflows, just removes bottom
popobj()80     void popobj()           { stack.add(stack.remove(0)); }            // never underflows, just puts it at the bottom
81 
removefromworld(rpgobj * worldobj)82     void removefromworld(rpgobj *worldobj)
83     {
84         objects.removeobj(worldobj);
85         DELETEP(worldobj->ent);
86     }
87 
taken(rpgobj * worldobj,rpgobj * newowner)88     void taken(rpgobj *worldobj, rpgobj *newowner)
89     {
90         removefromworld(worldobj);
91         newowner->add(worldobj, false);
92     }
93 
takefromplayer(char * name,char * ok,char * notok)94     void takefromplayer(char *name, char *ok, char *notok)
95     {
96         rpgobj *o = playerobj->take(name);
97         if(o)
98         {
99             stack[0]->add(o, false);
100             conoutf("\f2you hand over a %s", o->name);
101             if(currentquest)
102             {
103                 conoutf("\f2you finish a quest for %s", currentquest->npc);
104                 currentquest->completed = true;
105             }
106         }
107         execute(o ? ok : notok);
108     }
109 
givetoplayer(char * name)110     void givetoplayer(char *name)
111     {
112         rpgobj *o = stack[0]->take(name);
113         if(o)
114         {
115             conoutf("\f2you receive a %s", o->name);
116             playerobj->add(o, false);
117         }
118     }
119 
addquest(const char * questline,const char * npc)120     rpgquest *addquest(const char *questline, const char *npc)
121     {
122         quests = new rpgquest(quests, npc, questline);
123         conoutf("\f2you have accepted a quest for %s", npc);
124         return quests;
125     }
126 
listquests(bool completed,g3d_gui & g)127     void listquests(bool completed, g3d_gui &g)
128     {
129         for(rpgquest *q = quests; q; q = q->next) if(q->completed==completed)
130         {
131             defformatstring(info, "%s: %s", q->npc, q->questline);
132             g.text(info, 0xAAAAAA, "info");
133         }
134     }
135 
stringpool(char * name)136     char *stringpool(char *name)
137     {
138         char *exists = names.find(name, NULL);
139         if(exists) return exists;
140         return names.add(newstring(name));
141     }
142 
renderobjects()143     void renderobjects() { loopv(objects) objects[i]->render();   }
g3d_npcmenus()144     void g3d_npcmenus() { loopv(objects) objects[i]->g3d_menu(); }
145 
146     #define N(n) ICOMMAND(r_##n,     "i", (int *val), { stack[0]->s_##n = *val; }); \
147                  ICOMMAND(r_get_##n, "",  (), { intret(stack[0]->s_##n); });
148 
149     RPGNAMES
150     #undef N
151     #define N(n) ICOMMAND(r_def_##n, "ii", (int *i1, int *i2), { stats::def_##n(*i1, *i2); }); \
152                  ICOMMAND(r_eff_##n, "",   (), { intret(stack[0]->eff_##n()); });
153     RPGSTATNAMES
154     #undef N
155 
156     ICOMMAND(r_model,       "s",   (char *s), { stack[0]->model = stringpool(s); });
157     ICOMMAND(r_spawn,       "s",   (char *s), { spawn(stringpool(s)); });
158     ICOMMAND(r_contain,     "s",   (char *s), { stack[0]->decontain(); stack[1]->add(stack[0], atoi(s)); });
159     ICOMMAND(r_pop,         "",    (), { popobj(); });
160     ICOMMAND(r_swap,        "",    (), { swap(stack[0], stack[1]); });
161     ICOMMAND(r_say,         "s",   (char *s), { stack[0]->abovetext = stringpool(s); });
162     ICOMMAND(r_quest,       "ss",  (char *s, char *a), { stack[0]->addaction(stringpool(s), stringpool(a), true); });
163     ICOMMAND(r_action,      "ss",  (char *s, char *a), { stack[0]->addaction(stringpool(s), stringpool(a), false); });
164     ICOMMAND(r_action_use,  "s",   (char *s), { stack[0]->action_use.script = stringpool(s); });
165     ICOMMAND(r_take,        "sss", (char *name, char *ok, char *notok), { takefromplayer(name, ok, notok); });
166     ICOMMAND(r_give,        "s",   (char *s), { givetoplayer(s); });
167     ICOMMAND(r_use,         "",    (), { stack[0]->selectuse(); });
168     ICOMMAND(r_applydamage, "i",   (int *d), { stack[0]->takedamage(*d, *stack[1]); });
169 }
170 
171