#ifndef IGNORE_DEPEND #include #include #include #include #endif #include #include #include #include #include #include #include #include #include "npc.h" void NPC::SetDefaultMaterial(){ Lib3dsRgba a={0.2, 0.2, 0.2, 1.0}; Lib3dsRgba d={0.8, 0.8, 0.8, 1.0}; Lib3dsRgba s={0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); glMaterialf(GL_FRONT, GL_SHININESS, 0); } Lib3dsFile* NPC::Init3DS(const char* filename) { Lib3dsFile *file=0; file=lib3ds_file_load(filename); if (!file){ cerr<<"ERROR: loading "<childs; p!=0; p=p->next) Render3DSNode(file, p); } if (node->type==LIB3DS_OBJECT_NODE) { if (strcmp(node->name,"$$$DUMMY")==0) {return;} if (!node->user.d) { Lib3dsMesh *mesh=lib3ds_file_mesh_by_name(file, node->name); ASSERT(mesh); if (!mesh) {return;} node->user.d=glGenLists(1); glNewList(node->user.d, GL_COMPILE); { unsigned p; Lib3dsVector *normalL=(Lib3dsVector*)malloc(3*sizeof(Lib3dsVector)*mesh->faces); Lib3dsMatrix M; lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); lib3ds_mesh_calculate_normals(mesh, normalL); for (p=0; pfaces; ++p) { Lib3dsFace *f=&mesh->faceL[p]; Lib3dsMaterial *mat=0; if (f->material[0]) mat=lib3ds_file_material_by_name(file, f->material); if (mat) { glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); float s = 100*mat->shininess; glMaterialf(GL_FRONT, GL_SHININESS, s); }else { SetDefaultMaterial(); } { int i; glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (i=0; i<3; ++i) { glNormal3fv(normalL[3*p+i]); glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); } }//end for (mesh->faces) free(normalL); } glEndList(); }//end if (!node->user.d) if (node->user.d) { Lib3dsObjectData *d; glPushMatrix(); d=&node->data.object; glMultMatrixf(&node->matrix[0][0]); glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]); glCallList(node->user.d); glPopMatrix(); } } } void NPC::Render3DSModel (int modelID, int frame){ if(modelID<0 || modelID>=numModels){ //cout<<"bad modelID: "<totalFrames > 0; if((multiFile && model->files[frame] == NULL) || (!multiFile && model->files[0] == NULL)){ //cout<<"bad frame ("<loc)); glScalef(model->scale, model->scale, model->scale); glRotatef(model->theta, 0, 0, 1); glRotatef(model->phi, 0, 1, 0); Lib3dsNode *p; if (multiFile) { for (p=model->files[frame]->nodes; p!=0; p=p->next) Render3DSNode(model->files[frame], p); }else { lib3ds_file_eval(model->files[0], frame); for (p=model->files[0]->nodes; p!=0; p=p->next) Render3DSNode(model->files[0], p); } glDisable(GL_LIGHT0); glDisable(GL_LIGHTING); glPopAttrib(); } void NPC::RenderSimpleModel (int modelID){ glPushMatrix(); glEnable(GL_LIGHTING); glDisable(GL_LIGHT0); glDisable(GL_LIGHT1); glDisable(GL_LIGHT2); glEnable(GL_LIGHT0); GLfloat position0[]={0,1,0,1}; GLfloat ambient0[]={0,0,0,0.0}; GLfloat diffuse0[]={0.6,0.6,0.6,1.0};//was 0.7's glPushMatrix(); glLoadIdentity(); glLightfv(GL_LIGHT0,GL_POSITION,position0); glLightfv(GL_LIGHT0,GL_AMBIENT,ambient0); //was disabled glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse0); glPopMatrix(); SetDefaultMaterial(); switch(modelID){ case -1: glRotatef(90, 1,0,0); glutSolidTeapot(0.5); break; default: glutSolidSphere(1, 16,16); break; } glDisable(GL_LIGHT0); glDisable(GL_LIGHTING); glPopMatrix(); } void NPC::RenderModel(int modelID, int frame){ if(modelID>=0 && modelIDtotalFrames > 0; if((multiFile && model->files[frame] == NULL) || (!multiFile && model->files[0] == NULL)){ int refID = atoi(model->filename); //refernece Render3DSModel(refID, frame); }else //3DS model Render3DSModel(modelID, frame); }else{ //simple model RenderSimpleModel(modelID); } } int NPC::GetNumFrames(int modelID){ if(modelID>=0 && modelIDtotalFrames > 0; if(model->files[0] == NULL){ int refID = atoi(model->filename); if(refID>=0 && refIDtotalFrames > 0; if(ref->files[0] == NULL){ return 1; //invalid ref }else{ //ref to 3DS model if(multiFile) return ref->totalFrames; else return ref->files[0]->frames; } }else return 1; //ref to simple model }else { //3DS model if(multiFile) return model->totalFrames; else return model->files[0]->frames; } }else{ return 1; //simple model } } //--------------------------------------------------------------------- // NPC // // Method: Constructor // //--------------------------------------------------------------------- NPC::NPC(){ } //--------------------------------------------------------------------- // NPC // // Method: Destructor // //--------------------------------------------------------------------- NPC::~NPC(){ if (chars) delete[] chars; } //--------------------------------------------------------------------- // NPC // Method: Init // //! Initialize the course // //--------------------------------------------------------------------- bool NPC::Init(const char* npcFilename, conversation *conversationptr, coursecity *courseptr){ theconversation=conversationptr; thecoursecity=courseptr; char clearline[512]; ifstream is(npcFilename); cout<<"npcing on filename "<>clearline; is>>numModels; models = new (NPCModel) [sizeof(NPCModel)*numModels]; cout<<"Model: "<>clearline; for(int i = 0; i>models[i].scale>>models[i].loc.x>>models[i].loc.y>>models[i].loc.z; is>>models[i].theta>>models[i].phi; is>>models[i].totalFrames>>models[i].filename; models[i].files=new (Lib3dsFile*)[sizeof(Lib3dsFile*)*models[i].totalFrames]; if(models[i].totalFrames<=0) models[i].files[0] = Init3DS(models[i].filename); else{ char modelfile[1024]; for(int j = 0; j>clearline; is>>numChars; chars = new (NPCState) [sizeof(NPCState)*numChars]; cout<<"NPC: "<>clearline; for(int i = 0; i>chars[i].loc.x>>chars[i].loc.y>>chars[i].loc.z>>chars[i].theta>>chars[i].phi; //prevent it from getting confused about which tile it's in due to rounding error chars[i].loc.x+=0.05; chars[i].loc.y+=0.05; //read in type, model, state, text is>>chars[i].type>>chars[i].model>>chars[i].state;//>>chars[i].text; is.getline(chars[i].text,MAXTEXTSIZE,'\n'); chars[i].id=i; thecoursecity->AddDynamicObject((int)(chars[i].loc.x),(int)(chars[i].loc.y),i); chars[i].frame = 0; } return true; } bool NPC::RenderAll(CameraState* camera){ const float DIST = 30; int c = 0; for(int i = 0; ieye); float distB = Vector::distance(chars[i].loc, camera->at); if(distB > DIST) continue; //cout<= totalFrames-1) chars[i].frame = 0; else chars[i].frame++; } } } int NPC::addnpc(int type, int model, int state, vector3f position, float theta, float phi) { //not in yet-do we need this? it would mean copying the whole array return 0; } bool NPC::removenpc(int npcid) { if (npcid==-1) return false; chars[npcid].type=-1; if (chars[npcid].text) delete[] chars[npcid].text; thecoursecity->RemoveDynamicObject((int)(chars[npcid].loc.x),(int)(chars[npcid].loc.y)); return true; } bool NPC::doconversation(int npcid, int player) { cout<<"doing conversation "<StartConversation(player,chars[npcid].text); chars[npcid].talking=true; chars[npcid].frame = 0; //make the npc face the player *************************** return true; } bool NPC::KeepTalking(int npcid) { if (chars[npcid].talking) { int nearplayer=0; for (int x=(int)chars[npcid].loc.x-2; x<(int)chars[npcid].loc.x+3; x++) { for (int y=(int)chars[npcid].loc.y-2; y<(int)chars[npcid].loc.y+3; y++) { if (thecoursecity->coursemap[y*(thecoursecity->coursewidth)+x].contents>9999) nearplayer=1; } } if (nearplayer==0) { chars[npcid].talking=false;//no player is near so we don't need to keep still return false; } return true; } return false; } void NPC::AIZero(int npcid) { float oldx=(chars[npcid].loc.x); float oldy=(chars[npcid].loc.y); float newx=oldx; float newy=oldy;; if (chars[npcid].state<30) { newx=(chars[npcid].loc.x+0.1); } else if (chars[npcid].state<60) { newy=(chars[npcid].loc.y+0.1); } else if (chars[npcid].state<90) { newx=(chars[npcid].loc.x-0.1); } else if (chars[npcid].state<120) { newy=(chars[npcid].loc.y-0.1); } if ( (newx!=oldx) || (newy!=oldy)) if (chars[npcid].state<120) if (thecoursecity->CheckCollision(oldx,oldy,chars[npcid].loc.z,newx,newy,chars[npcid].loc.z,npcid)==false) { chars[npcid].loc.x=newx; chars[npcid].loc.y=newy; if (((int)newx!=(int)oldx)||((int)newy!=(int)oldy)) thecoursecity->MoveDynamicObject((int)oldx,(int)oldy,(int)newx,(int)newy); } else { //if (npcid==3) cout<<"npc "<120) chars[npcid].state=0; } void NPC::AIOne(int id){ chars[id].state = (chars[id].state + 1)%10; //cout<CheckCollision2(newLoc, id, 1, false)==-1) { //if (thecoursecity->CheckCollision(V3COMP(chars[id].loc),V3COMP(newLoc),id)==false) { if (thecoursecity->CheckCollision(chars[id].loc.x,chars[id].loc.y,3,newLoc.x,newLoc.y,3,id)==false) { if (((int)chars[id].loc.x!=(int)newLoc.x)||((int)chars[id].loc.y!=(int)newLoc.y)) //thecoursecity->MoveDynamicObject2(chars[id].loc, newLoc, id); thecoursecity->MoveDynamicObject((int)(chars[id].loc.x),(int)(chars[id].loc.y),(int)(newLoc.x),(int)(newLoc.y)); chars[id].loc = newLoc; }else{ chars[id].theta+=90; } } }