コード例 #1
0
ファイル: xio-ip.c プロジェクト: Adastra-thw/Tortazo
/* the ultimate(?) socat resolver function
 node: the address to be resolved; supported forms:
   1.2.3.4 (IPv4 address)
   [::2]   (IPv6 address)
   hostname (hostname resolving to IPv4 or IPv6 address)
   hostname.domain (fq hostname resolving to IPv4 or IPv6 address)
 service: the port specification; may be numeric or symbolic
 family: PF_INET, PF_INET6, or PF_UNSPEC permitting both
 socktype: SOCK_STREAM, SOCK_DGRAM
 protocol: IPPROTO_UDP, IPPROTO_TCP
 sau: an uninitialized storage for the resulting socket address
 returns: STAT_OK, STAT_RETRYLATER
*/
int xiogetaddrinfo(const char *node, const char *service,
		   int family, int socktype, int protocol,
		   union sockaddr_union *sau, socklen_t *socklen,
		   unsigned long res_opts0, unsigned long res_opts1) {
   int port = -1;	/* port number in network byte order */
   char *numnode = NULL;
   size_t nodelen;
   unsigned long save_res_opts = 0;
#if HAVE_GETADDRINFO
   struct addrinfo hints = {0};
   struct addrinfo *res = NULL;
#else /* HAVE_PROTOTYPE_LIB_getipnodebyname || nothing */
   struct hostent *host;
#endif
   int error_num;

#if HAVE_RESOLV_H
   if (res_opts0 | res_opts1) {
      if (!(_res.options & RES_INIT)) {
         Res_init();	/*!!! returns -1 on error */
      }
      save_res_opts = _res.options;
      _res.options &= ~res_opts0;
      _res.options |= res_opts1;
      Debug2("changed _res.options from 0x%lx to 0x%lx",
	     save_res_opts, _res.options);
   }
#endif /* HAVE_RESOLV_H */
   memset(sau, 0, *socklen);
   sau->soa.sa_family = family;

   /* if service is numeric we don't want to have a lookup (might take long
      with NIS), so we handle this specially */
   if (service && isdigit(service[0]&0xff)) {
      char *extra;
      port = htons(strtoul(service, &extra, 0));
      if (*extra != '\0') {
	 Warn2("xiogetaddrinfo(, \"%s\", ...): extra trailing data \"%s\"",
	       service, extra);
      }
      service = NULL; 
   }

   /* the resolver functions might handle numeric forms of node names by
      reverse lookup, that's not what we want.
      So we detect these and handle them specially */
   if (node && isdigit(node[0]&0xff)) {
#if HAVE_GETADDRINFO
      hints.ai_flags |= AI_NUMERICHOST;
#endif /* HAVE_GETADDRINFO */
      if (family == PF_UNSPEC) {
	 family = PF_INET;
#if HAVE_GETADDRINFO
      } else if (family == PF_INET6) {
	 /* map "explicitely" into IPv6 address space; getipnodebyname() does
	    this with AI_V4MAPPED, but not getaddrinfo() */
	 if ((numnode = Malloc(strlen(node)+7+1)) == NULL) {
#if HAVE_RESOLV_H
	    if (res_opts0 | res_opts1) {
	       _res.options = (_res.options & (~res_opts0&~res_opts1) |
			       save_res_opts& ( res_opts0| res_opts1));
	    }
#endif
	    return STAT_NORETRY;
	 }
	 sprintf(numnode, "::ffff:%s", node);
	 node = numnode;
	 hints.ai_flags |= AI_NUMERICHOST;
#endif /* HAVE_GETADDRINFO */
      }
#if WITH_IP6
   } else if (node && node[0] == '[' && node[(nodelen=strlen(node))-1]==']') {
      if ((numnode = Malloc(nodelen-1)) == NULL) {
#if HAVE_RESOLV_H
	 if (res_opts0 | res_opts1) {
	    _res.options = (_res.options & (~res_opts0&~res_opts1) |
			    save_res_opts& ( res_opts0| res_opts1));
	 }
#endif
	 return STAT_NORETRY;
      }
      strncpy(numnode, node+1, nodelen-2);	/* ok */
      numnode[nodelen-2] = '\0';
      node = numnode;
#if HAVE_GETADDRINFO
      hints.ai_flags |= AI_NUMERICHOST;
#endif /* HAVE_GETADDRINFO */
      if (family == PF_UNSPEC)  family = PF_INET6;
#endif /* WITH_IP6 */
   }

#if HAVE_GETADDRINFO
   if (node != NULL || service != NULL) {
      struct addrinfo *record;

      if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM) {
	 /* actual socket type value is not supported - fallback to a good one */
	 socktype = SOCK_DGRAM;
      }
      if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) {
	 /* actual protocol value is not supported - fallback to a good one */
	 if (socktype == SOCK_DGRAM) {
	    protocol = IPPROTO_UDP;
	 } else {
	    protocol = IPPROTO_TCP;
	 }
      }
      hints.ai_flags |= AI_PASSIVE;
      hints.ai_family = family;
      hints.ai_socktype = socktype;
      hints.ai_protocol = protocol;
      hints.ai_addrlen = 0;
      hints.ai_addr = NULL;
      hints.ai_canonname = NULL;
      hints.ai_next = NULL;

      if ((error_num = Getaddrinfo(node, service, &hints, &res)) != 0) {
	 Error7("getaddrinfo(\"%s\", \"%s\", {%d,%d,%d,%d}, {}): %s",
		node, service, hints.ai_flags, hints.ai_family,
		hints.ai_socktype, hints.ai_protocol,
		(error_num == EAI_SYSTEM)?
		strerror(errno):gai_strerror(error_num));
	 if (res != NULL)  freeaddrinfo(res);
	 if (numnode)  free(numnode);

#if HAVE_RESOLV_H
	 if (res_opts0 | res_opts1) {
	    _res.options = (_res.options & (~res_opts0&~res_opts1) |
			    save_res_opts& ( res_opts0| res_opts1));
	 }
#endif
	 return STAT_RETRYLATER;
      }
      service = NULL;	/* do not resolve later again */

      record = res;
      if (family == PF_UNSPEC && xioopts.preferred_ip == '0') {
	 /* we just take the first result */
	 family = res[0].ai_addr->sa_family;
      }
      if (family == PF_UNSPEC) {
	 int trypf;
	 trypf = (xioopts.preferred_ip=='6'?PF_INET6:PF_INET);
	 /* we must look for a matching entry */
	 while (record != NULL) {
	    if (record->ai_family == trypf) {
	       family = trypf;
	       break;	/* family and record set accordingly */
	    }
	    record = record->ai_next;
	 }
	 if (record == NULL) {
	    /* we did not find a "preferred" entry, take the first */
	    record = res;
	    family = res[0].ai_addr->sa_family;
	 }
      }

      switch (family) {
#if WITH_IP4
      case PF_INET:
	 if (*socklen > record->ai_addrlen) {
	    *socklen = record->ai_addrlen;
	 }
	 memcpy(&sau->ip4, record->ai_addr, *socklen);
	 break;
#endif /* WITH_IP4 */
#if WITH_IP6
      case PF_INET6:
#if _AIX
	 /* older AIX versions pass wrong length, so we correct it */
	 record->ai_addr->sa_len = sizeof(struct sockaddr_in6);
#endif
	 if (*socklen > record->ai_addrlen) {
	    *socklen = record->ai_addrlen;
	 }
	 memcpy(&sau->ip6, record->ai_addr, *socklen);
	 break;
#endif /* WITH_IP6 */
      default:
	 Error1("address resolved to unknown protocol family %d",
		record->ai_addr->sa_family);
	 break;
      }
      freeaddrinfo(res);
   } else {
      switch (family) {
#if WITH_IP4
      case PF_INET:  *socklen = sizeof(sau->ip4); break;
#endif /* WITH_IP4 */
#if WITH_IP6
      case PF_INET6: *socklen = sizeof(sau->ip6); break;
#endif /* WITH_IP6 */
      }
   }

#elif HAVE_PROTOTYPE_LIB_getipnodebyname /* !HAVE_GETADDRINFO */

   if (node != NULL) {
      /* first fallback is getipnodebyname() */
      if (family == PF_UNSPEC) {
#if WITH_IP4 && WITH_IP6
	 family = xioopts.default_ip=='6'?PF_INET6:PF_INET;
#elif WITH_IP6
	 family = PF_INET6;
#else
	 family = PF_INET;
#endif
      }
      host = Getipnodebyname(node, family, AI_V4MAPPED, &error_num);
      if (host == NULL) {
	 const static char ai_host_not_found[] = "Host not found";
	 const static char ai_no_address[]     = "No address";
	 const static char ai_no_recovery[]    = "No recovery";
	 const static char ai_try_again[]      = "Try again";
	 const char *error_msg = "Unknown error";
	 switch (error_num) {
	 case HOST_NOT_FOUND: error_msg = ai_host_not_found; break;
	 case NO_ADDRESS:     error_msg = ai_no_address;
	 case NO_RECOVERY:    error_msg = ai_no_recovery;
	 case TRY_AGAIN:      error_msg = ai_try_again;
	 }
	 Error2("getipnodebyname(\"%s\", ...): %s", node, error_msg);
      } else {
	 switch (family) {
#if WITH_IP4
	 case PF_INET:
	    *socklen = sizeof(sau->ip4);
	    sau->soa.sa_family = PF_INET;
	    memcpy(&sau->ip4.sin_addr, host->h_addr_list[0], 4);
	    break;
#endif
#if WITH_IP6
	 case PF_INET6:
	    *socklen = sizeof(sau->ip6);
	    sau->soa.sa_family = PF_INET6;
	    memcpy(&sau->ip6.sin6_addr, host->h_addr_list[0], 16);
	    break;
#endif
	 }
      }
      freehostent(host);
   }

#else /* !HAVE_PROTOTYPE_LIB_getipnodebyname */

   if (node != NULL) {
      /* this is not a typical IP6 resolver function - but Linux
	 "man gethostbyname" says that the only supported address type with
	 this function is AF_INET _at present_, so maybe this fallback will
	 be useful somewhere sometimesin a future even for IP6 */
      if (family == PF_UNSPEC) {
#if WITH_IP4 && WITH_IP6
	 family = xioopts.default_ip=='6'?PF_INET6:PF_INET;
#elif WITH_IP6
	 family = PF_INET6;
#else
	 family = PF_INET;
#endif
      }
      /*!!! try gethostbyname2 for IP6 */
      if ((host = Gethostbyname(node)) == NULL) {
	 Error2("gethostbyname(\"%s\"): %s", node,
		h_errno == NETDB_INTERNAL ? strerror(errno) :
		hstrerror(h_errno));
#if HAVE_RESOLV_H
	 if (res_opts0 | res_opts1) {
	    _res.options = (_res.options & (~res_opts0&~res_opts1) |
			    save_res_opts& ( res_opts0| res_opts1));
	 }
#endif
	 return STAT_RETRYLATER;
      }
      if (host->h_addrtype != family) {
	 Error2("xioaddrinfo(): \"%s\" does not resolve to %s",
		node, family==PF_INET?"IP4":"IP6");
      } else {
	 switch (family) {
#if WITH_IP4
	 case PF_INET:
	    *socklen = sizeof(sau->ip4);
	    sau->soa.sa_family = PF_INET;
	    memcpy(&sau->ip4.sin_addr, host->h_addr_list[0], 4);
	    break;
#endif /* WITH_IP4 */
#if WITH_IP6
	 case PF_INET6:
	    *socklen = sizeof(sau->ip6);
	    sau->soa.sa_family = PF_INET6;
	    memcpy(&sau->ip6.sin6_addr, host->h_addr_list[0], 16);
	    break;
#endif /* WITH_IP6 */
	 }
      }
   }

#endif

#if WITH_TCP || WITH_UDP
   if (service) {
      port = parseport(service, protocol);
   }
   if (port >= 0) {
      switch (family) {
#if WITH_IP4
      case PF_INET:  sau->ip4.sin_port  = port; break;
#endif /* WITH_IP4 */
#if WITH_IP6
      case PF_INET6: sau->ip6.sin6_port = port; break;
#endif /* WITH_IP6 */
      }
   }      
#endif /* WITH_TCP || WITH_UDP */

   if (numnode)  free(numnode);

#if HAVE_RESOLV_H
   if (res_opts0 | res_opts1) {
      _res.options = (_res.options & (~res_opts0&~res_opts1) |
		      save_res_opts& ( res_opts0| res_opts1));
   }
#endif /* HAVE_RESOLV_H */
   return STAT_OK;
}
コード例 #2
0
ファイル: socat.c プロジェクト: dest-unreach/socat2
int main(int argc, const char *argv[]) {
   const char **arg1, *a;
   char *mainwaitstring;
   char buff[10];
   double rto;
   int i, argc0, result;
   struct utsname ubuf;
   int lockrc;

   if (mainwaitstring = getenv("SOCAT_MAIN_WAIT")) {
       sleep(atoi(mainwaitstring));
   }
   diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);

   /* we must init before applying options because env settings have lower
      priority and are to be overridden by options */
   if (xioinitialize(XIO_MAYALL) != 0) {
      Exit(1);
   }

   xiosetopt('p', "%");
   xiosetopt('o', ":");

   argc0 = argc;	/* save for later use */
   arg1 = argv+1;  --argc;
   while (arg1[0] && (arg1[0][0] == '-')) {
      switch (arg1[0][1]) {
      case 'V': socat_version(stdout); Exit(0);
#if WITH_HELP
      case '?':
      case 'h':
	 socat_usage(stdout);
	 xioopenhelp(stdout, (arg1[0][2]=='?'||arg1[0][2]=='h') ? (arg1[0][3]=='?'||arg1[0][3]=='h') ? 2 : 1 : 0);
	 Exit(0);
#endif /* WITH_HELP */
      case 'd': diag_set('d', NULL); break;
#if WITH_FILAN
      case 'D': xioparams->debug = true; break;
#endif
      case 'l':
	 switch (arg1[0][2]) {
	 case 'm': /* mixed mode: stderr, then switch to syslog; + facility */
	    diag_set('s', NULL);
	    xiosetopt('l', "m");
	    xioparams->logopt = arg1[0][2];
	    xiosetopt('y', &arg1[0][3]);
	    break;
	 case 'y': /* syslog + facility */
	    diag_set(arg1[0][2], &arg1[0][3]);
	    break;
	 case 'f': /* to file, +filename */
	 case 'p': /* artificial program name */
	    if (arg1[0][3]) {
	       diag_set(arg1[0][2], &arg1[0][3]);
	    } else if (arg1[1]) {
	       diag_set(arg1[0][2], arg1[1]);
	       ++arg1, --argc;
	    } else {
	       Error1("option -l%c requires an argument; use option \"-h\" for help", arg1[0][2]);
	    }
	    break;
	 case 's': /* stderr */
	    diag_set(arg1[0][2], NULL);
	    break;
	 case 'u':
	    diag_set('u', NULL);
	    break;
	 case 'h':
	    diag_set_int('h', true);
	    break;
	 default:
	    Error1("unknown log option \"%s\"; use option \"-h\" for help", arg1[0]);
	    break;
	 }
	 break;
      case 'v': xioparams->verbose = true; break;
      case 'x': xioparams->verbhex = true; break;
      case 'b': if (arg1[0][2]) {
	    a = *arg1+2;
	 } else {
	    ++arg1, --argc;
	    if ((a = *arg1) == NULL) {
	       Error("option -b requires an argument; use option \"-h\" for help");
	       Exit(1);
	    }
	 }
	 xioparams->bufsiz = strtoul(a, (char **)&a, 0);
	 break;
      case 's':
	 diag_set_int('e', E_FATAL); break;
      case 't': if (arg1[0][2]) {
	    a = *arg1+2;
	 } else {
	    ++arg1, --argc;
	    if ((a = *arg1) == NULL) {
	       Error("option -t requires an argument; use option \"-h\" for help");
	       Exit(1);
	    }
	 }
	 rto = strtod(a, (char **)&a);
	 xioparams->closwait.tv_sec = rto;
	 xioparams->closwait.tv_usec =
	    (rto-xioparams->closwait.tv_sec) * 1000000; 
	 break;
      case 'T':  if (arg1[0][2]) {
	    a = *arg1+2;
	 } else {
	    ++arg1, --argc;
	    if ((a = *arg1) == NULL) {
	       Error("option -T requires an argument; use option \"-h\" for help");
	       Exit(1);
	    }
	 }
	 rto = strtod(a, (char **)&a);
	 xioparams->total_timeout.tv_sec = rto;
	 xioparams->total_timeout.tv_usec =
	    (rto-xioparams->total_timeout.tv_sec) * 1000000; 
	 break;
      case 'u': xioparams->lefttoright = true; break;
      case 'U': xioparams->righttoleft = true; break;
      case 'g': xioopts_ignoregroups = true; break;
      case 'L': if (socat_opts.lock.lockfile)
	     Error("only one -L and -W option allowed");
	 if (arg1[0][2]) {
	    socat_opts.lock.lockfile = *arg1+2;
	 } else {
	    ++arg1, --argc;
	    if ((socat_opts.lock.lockfile = *arg1) == NULL) {
	       Error("option -L requires an argument; use option \"-h\" for help");
	       Exit(1);
	    }
	 }
	 break;
      case 'W': if (socat_opts.lock.lockfile)
	    Error("only one -L and -W option allowed");
	 if (arg1[0][2]) {
	    socat_opts.lock.lockfile = *arg1+2;
	 } else {
	    ++arg1, --argc;
	    if ((socat_opts.lock.lockfile = *arg1) == NULL) {
	       Error("option -W requires an argument; use option \"-h\" for help");
	       Exit(1);
	    }
	 }
	 socat_opts.lock.waitlock = true;
	 socat_opts.lock.intervall.tv_sec  = 1;
	 socat_opts.lock.intervall.tv_nsec = 0;
	 break;
#if WITH_IP4 || WITH_IP6
#if WITH_IP4
      case '4':
#endif
#if WITH_IP6
      case '6':
#endif
	 xioopts.default_ip = arg1[0][1];
	 xioopts.preferred_ip = arg1[0][1];
	 break;
#endif /* WITH_IP4 || WITH_IP6 */
      case 'c':
	 switch (arg1[0][2]) {
	 case 'S': xioparams->pipetype = XIOCOMM_SOCKETPAIRS; break;
	 case 'P':
	 case 'p': xioparams->pipetype = XIOCOMM_PIPES;       break;
	 case 's': xioparams->pipetype = XIOCOMM_SOCKETPAIR;  break;
	 case 'Y': xioparams->pipetype = XIOCOMM_PTYS;        break;
	 case 'y': xioparams->pipetype = XIOCOMM_PTY;         break;
	 case 't': xioparams->pipetype = XIOCOMM_TCP;         break;
	 case '0': case '1': case '2': case '3': case '4':
	 case '5': case '6': case '7': case '8': case '9':
	    xioparams->pipetype = atoi(&arg1[0][2]); break;
	 default: Error1("bad chain communication type \"%s\"", &arg1[0][2]);
	 }
	 break;
      case '\0':
      case '-':	/*! this is hardcoded "--" */
      case ',':
      case ':': break;	/* this "-" is a variation of STDIO or -- */
      default:
	 xioinqopt('p', buff, sizeof(buff));
	 if (arg1[0][1] == buff[0]) {
	    break;
	 }
	 Error1("unknown option \"%s\"; use option \"-h\" for help", arg1[0]);
	 Exit(1);
      }
      /* the leading "-" might be a form of the first address */
      xioinqopt('p', buff, sizeof(buff));
      if (arg1[0][0] == '-' &&
	  (arg1[0][1] == '\0' || arg1[0][1] == ':' ||
	   arg1[0][1] == ',' || arg1[0][1] == '-'/*!*/ ||
	   arg1[0][1] == buff[0]))
	 break;
      ++arg1; --argc;
   }
#if 0
   Info1("%d address arguments", argc);
#else
   if (argc != 2) {
      Error1("exactly 2 addresses required (there are %d); use option \"-h\" for help", argc);
      Exit(1);
   }
#endif
   if (xioparams->lefttoright && xioparams->righttoleft) {
      Error("-U and -u must not be combined");
   }

   xioinitialize2();
   Info(copyright_socat);
#if WITH_OPENSSL
   Info(copyright_openssl);
   Info(copyright_ssleay);
#endif
   Debug2("socat version %s on %s", socatversion, timestamp);
   xiosetenv("VERSION", socatversion, 1);	/* SOCAT_VERSION */
   uname(&ubuf);	/* ! here we circumvent internal tracing (Uname) */
   Debug4("running on %s version %s, release %s, machine %s\n",
	   ubuf.sysname, ubuf.version, ubuf.release, ubuf.machine);

#if WITH_MSGLEVEL <= E_DEBUG
   for (i = 0; i < argc0; ++i) {
      Debug2("argv[%d]: \"%s\"", i, argv[i]);
   }
#endif /* WITH_MSGLEVEL <= E_DEBUG */

   /* not sure what signal should print a message */
   Signal(SIGHUP, socat_signal);
   Signal(SIGINT, socat_signal);
   Signal(SIGQUIT, socat_signal);
   Signal(SIGILL, socat_signal);
   /* SIGABRT for assert; catching caused endless recursion on assert in libc
      (tzfile.c:498: __tzfile_compute: Assertion 'num_types == 1' failed.) */
   /*Signal(SIGABRT, socat_signal);*/
   Signal(SIGBUS, socat_signal);
   Signal(SIGFPE, socat_signal);
   Signal(SIGSEGV, socat_signal);
   Signal(SIGTERM, socat_signal);
#if HAVE_SIGACTION
   {
      struct sigaction act;
      memset(&act, 0, sizeof(struct sigaction));
      act.sa_flags   = SA_NOCLDSTOP|SA_RESTART|SA_SIGINFO
#ifdef SA_NOMASK
	 |SA_NOMASK
#endif
	 ;
      act.sa_sigaction = xiosigaction_subaddr_ok;
      if (Sigaction(SIGUSR1, &act, NULL) < 0) {
	 /*! Linux man does not explicitely say that errno is defined */
	 Warn1("sigaction(SIGUSR1, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
      }
   }
#else /* !HAVE_SIGACTION */
   if (Signal(SIGUSR1, xiosigaction_subaddr_ok) == SIG_ERR) {
      Warn1("signal(SIGCHLD, xiosigaction_subaddr_ok): %s", strerror(errno));
   }
#endif /* !HAVE_SIGACTION */

   /* set xio hooks */
   xiohook_newchild = &socat_newchild;

   if (lockrc = socat_lock()) {
      /* =0: goon; >0: locked; <0: error, printed in sub */
      if (lockrc > 0)
	 Error1("could not obtain lock \"%s\"", socat_opts.lock.lockfile);
      Exit(1);
   }

   Atexit(socat_unlock);

   result = socat(argc, arg1[0], arg1[1]);
   Notice1("exiting with status %d", result);
   Exit(result);
   return 0;	/* not reached, just for gcc -Wall */
}
コード例 #3
0
ファイル: advicemanager.cpp プロジェクト: garinh/planeshift
void AdviceManager::HandleAdviceResponse( Client *advisor, csString sAdvisee, csString message)
{
    if ( !advisor->GetAdvisor() )
    {
        psserver->SendSystemInfo(advisor->GetClientNum(),"You need to be an advisor to use this command.");
        return;
    }

    csString buf;
    // Source Client Name, Target Client Name, Message
    buf.Format("%s, %s, \"%s\"", advisor->GetName(), sAdvisee.GetData() , message.GetData());
    psserver->GetLogCSV()->Write(CSV_ADVICE, buf);

    // Find Advisee Client by name
    if (sAdvisee.Length())
    {
        sAdvisee = NormalizeCharacterName(sAdvisee);
    }
    Client *advisee = psserver->GetConnections()->Find(sAdvisee);
    if (!advisee)
    {
        // Create a new message to report TELL error and send
        // back to original person.
        csString sMsg("No player named ");
        sMsg += sAdvisee;
        sMsg += " is logged on to the system currently.";
        psserver->SendSystemError(advisor->GetClientNum(), sMsg);
        return;
    }

    // Can't allow you to advise yourself
    if ( advisee == advisor )
    {
        psserver->SendSystemError(advisor->GetClientNum(), "You are not allowed to advise yourself. Please wait for another advisor.");
        return;
    }

    // find existing Advicee in the List
    AdviceSession key;
    key.AdviseeClientNum = advisee->GetClientNum();
    AdviceSession *activeSession = AdviseeList.Get(advisee->GetClientNum(), NULL);

    if (!activeSession || (activeSession  && ( !activeSession->requestEvent ) && ( activeSession->GetAdvisor() == NULL ) ) )
    {
        psserver->SendSystemError(advisor->GetClientNum(), "%s has not requested help.", advisee->GetName());
        return;
    }

    if (activeSession  && ( activeSession->AdviseeClientNum != advisee->GetClientNum() ) )
    {
        Debug2( LOG_ANY, advisee->GetClientNum(), "Grabbed wrong advisor session: %d", activeSession->AdviseeClientNum );
    }

    if ( ( activeSession->GetAdvisor() != NULL ) && ( activeSession->AdvisorClientNum != advisor->GetClientNum() ) )
    {
        psserver->SendSystemError(advisor->GetClientNum(), "%s is being advised already, thank you.",  advisee->GetName());
        return;
    }

    if ( message.Length() == 0  && activeSession->status == SESSION_STATUS_UNKNOWN ) // advisor is claiming a session
    {
        // check to make sure advisor has only one claimed session.
        AdviceSession *loopSession;

        csHash< AdviceSession* >::GlobalIterator loop( AdviseeList.GetIterator() );

        while(loop.HasNext())
        {
        	loopSession = loop.Next();
            if (activeSession->status == SESSION_STATUS_CLAIMED && loopSession->GetAdvisor() == advisor )
            {
                psserver->SendSystemInfo(advisor->GetClientNum(), "You cannot have two messengers waiting for you at the same time, please answer %s's request first." , loopSession->adviseeName.GetData() );
                return;
            }
        }

        activeSession->SetAdvisor( advisor );
        psserver->SendSystemInfo(advisee->GetClientNum(), "An advisor is preparing an answer to your question, please be patient.");
        psserver->SendSystemInfo(advisor->GetClientNum(), "You have claimed the session with %s. Please provide an answer." , advisee->GetName() );

        for (size_t i = 0; i < advisors.GetSize(); i++)
        {
            if ( advisors[i].id != activeSession->AdvisorClientNum )
            {
                psserver->SendSystemInfo(advisors[i].id, "%s has proclaimed they know the answer to %s's question.", advisor->GetName(), advisee->GetName() );
            }
        }
        activeSession->status = SESSION_STATUS_CLAIMED;
    }
    else
    {
        if (message.IsEmpty())
        {
            psserver->SendSystemInfo(advisor->GetClientNum(), "Please enter the advice you wish to give.");
            return;
        }

        psChatMessage msgChat(activeSession->AdviseeClientNum, 0, advisor->GetName(), advisee->GetName(), message ,CHAT_ADVISOR,false);

        if ( activeSession->GetAdvisor() == NULL || activeSession->status != SESSION_STATUS_OWNED )
        {
            // Check to make sure the advice is 'good'
            // if ( message.Length() < 20 )
            // {
                // psserver->SendSystemInfo(advisor->GetClientNum(), "Please be more specific when answering questions. Your advice has been ignored.");
                // return;
            // }

            //activeSession->AdvisorClientNum = me->clientnum;
            activeSession->SetAdvisor( advisor );
            advisor->IncrementAdvisorPoints(activeSession->advisorPoints);
            psserver->CharacterLoader.SaveCharacterData( advisor->GetCharacterData(), advisor->GetActor(), true );

            // Send Confirmation to advisor
            psserver->SendSystemInfo( advisor->GetClientNum(), "You are now advising %s.",advisee->GetName());

            // Send Confirmation to all other advisors so they know they lost this one.
            for (size_t i = 0; i < advisors.GetSize(); i++)
            {
                if ( advisors[i].id != activeSession->AdvisorClientNum )
                {
                    psserver->SendSystemInfo( advisors[i].id, "%s has been assigned to %s.",  advisee->GetName(), advisor->GetName() );
                    if ( advisors[i].GM )
                        continue;
                    msgChat.msg->clientnum = advisors[i].id;
                    msgChat.SendMessage();
                }
            }
            activeSession->status = SESSION_STATUS_OWNED;
        }

        if ( activeSession->requestEvent )
            activeSession->requestEvent->valid = false;  // This keeps the cancellation timeout from firing.

        activeSession->answered = true;

        // Send Message to Advisee
        msgChat.msg->clientnum = activeSession->AdviseeClientNum;
        msgChat.SendMessage();

        // Send Message to advisor
        msgChat.msg->clientnum = activeSession->AdvisorClientNum;
        msgChat.SendMessage();

        // Send message to GM chars as well
        for (size_t i = 0; i < advisors.GetSize(); i++)
        {
            if (!advisors[i].GM || advisors[i].id == activeSession->AdvisorClientNum)
                continue;
            msgChat.msg->clientnum = advisors[i].id;
            msgChat.SendMessage();
        }
    }

    // Add timeout for Advisor-Advisee relationship
    // this will allow later questions by the same client to go to a different advisor
    // spreading the wealth and burden amongst all ;)
    if ( activeSession->timeoutEvent )
    {
        activeSession->timeoutEvent->valid = false;
    }
    psAdviceSessionTimeoutGameEvent *ev = new psAdviceSessionTimeoutGameEvent( this, activeSession->answered?ADVICE_SESSION_TIMEOUT:ADVICE_SESSION_TIMEOUT/2, advisee->GetActor(), activeSession );
    activeSession->timeoutEvent = ev;
    psserver->GetEventManager()->Push(ev);

}
コード例 #4
0
void CombatManager::HandleCombatEvent(psCombatGameEvent *event)
{
    psCharacter *attacker_data,*target_data;
    int attack_result;
    bool skipThisRound = false;

    if (!event->GetAttacker() || !event->GetTarget()) // disconnected and deleted
    {
#ifdef COMBAT_DEBUG
        psserver->SendSystemError(event->AttackerCID, "Combat stopped as one participant logged of.");
#endif
        return;
    }

    gemActor *gemAttacker = dynamic_cast<gemActor*> ((gemObject *) event->attacker);
    gemActor *gemTarget   = dynamic_cast<gemActor*> ((gemObject *) event->target);

    attacker_data=event->GetAttackerData();
    target_data=event->GetTargetData();

    // If the attacker is no longer in attack mode abort.
    if (gemAttacker->GetMode() != PSCHARACTER_MODE_COMBAT)
    {
#ifdef COMBAT_DEBUG
        psserver->SendSystemError(event->AttackerCID,
                "Combat stopped as you left combat mode.");
#endif
        return;
    }

    // If target is dead, abort.
    if (!gemTarget->IsAlive() )
    {
#ifdef COMBAT_DEBUG
        psserver->SendSystemResult(event->AttackerCID, "Combat stopped as one participant logged of.");
#endif
        return;
    }

    // If the slot is no longer attackable, abort
    if (!attacker_data->Inventory().CanItemAttack(event->GetWeaponSlot()))
    {
#ifdef COMBAT_DEBUG
        psserver->SendSystemError(event->AttackerCID, "Combat stopped as you have no longer an attackable item equipped.");
#endif
        return;
    }
    
    if (attacker_data->Inventory().GetEquipmentObject(event->GetWeaponSlot()).eventId != event->id)
    {
#ifdef COMBAT_DEBUG
        psserver->SendSystemError(event->AttackerCID, "Ignored combat event as newer is in.");
#endif
        return;
    }
   
    psItem* weapon = attacker_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot());

    // weapon became unwieldable
    csString response;
    if(weapon!=NULL && !weapon->CheckRequirements(attacker_data,response))
    {
        Debug2(LOG_COMBAT, gemAttacker->GetClientID(),"%s has lost use of weapon", gemAttacker->GetName() );
        psserver->SendSystemError(event->AttackerCID, "You can't use your %s any more.", weapon->GetName() );
        return;
    }

    // If the weapon in the slot has been changed, skip a turn (latency for this slot may also have changed)
    if (event->WeaponID != weapon->GetUID())
    {
        Debug2(LOG_COMBAT, gemAttacker->GetClientID(),"%s has changed weapons mid battle", gemAttacker->GetName() );
#ifdef COMBAT_DEBUG
        psserver->SendSystemError(event->AttackerCID, "Weapon changed. Skipping");
#endif
        skipThisRound = true;
    }

    Client * attacker_client = psserver->GetNetManager()->GetClient(event->AttackerCID);
    if (attacker_client)
    {
        // Input the stamina data
        MathEnvironment env;
        env.Define("Actor",  event->GetAttacker());
        env.Define("Weapon", weapon);
        staminacombat->Evaluate(&env);
        MathVar *PhyDrain = env.Lookup("PhyDrain");
        MathVar *MntDrain = env.Lookup("MntDrain");

        if ( (attacker_client->GetCharacterData()->GetStamina(true) < PhyDrain->GetValue())
            || (attacker_client->GetCharacterData()->GetStamina(false) < MntDrain->GetValue()) )
        {
           StopAttack(attacker_data->GetActor());
           psserver->SendSystemError(event->AttackerCID, "You are too tired to attack.");
           return;
        }

        // If the target has become impervious, abort and give up attacking
        if (!attacker_client->IsAllowedToAttack(gemTarget))
        {
           StopAttack(attacker_data->GetActor());
           return;
        }

        // If the target has changed, abort (assume another combat event has started since we are still in attack mode)
        if (gemTarget != attacker_client->GetTargetObject())
        {
#ifdef COMBAT_DEBUG
            psserver->SendSystemError(event->AttackerCID, "Target changed.");
#endif
            return;
        }
    }
    else
    {
        // Check if the npc's target has changed (if it has, then assume another combat event has started.)
        gemNPC* npcAttacker = dynamic_cast<gemNPC*>(gemAttacker);
        if (npcAttacker && npcAttacker->GetTarget() != gemTarget)
        {
#ifdef COMBAT_DEBUG
            psserver->SendSystemError(event->AttackerCID, "NPC's target changed.");
#endif
            return;
        }
    }

    if (gemAttacker->IsSpellCasting())
    {
        psserver->SendSystemInfo(event->AttackerCID, "You can't attack while casting spells.");
        skipThisRound = true;
    }

    if (!skipThisRound)
    {
        if (weapon->GetIsRangeWeapon() && weapon->GetUsesAmmo())
        {
            INVENTORY_SLOT_NUMBER otherHand = event->GetWeaponSlot() == PSCHARACTER_SLOT_RIGHTHAND ?
                                                                        PSCHARACTER_SLOT_LEFTHAND:
                                                                        PSCHARACTER_SLOT_RIGHTHAND;

            attack_result = ATTACK_NOTCALCULATED;

            psItem* otherItem = attacker_data->Inventory().GetInventoryItem(otherHand);
            if (otherItem == NULL)
            {
                attack_result = ATTACK_OUTOFAMMO;
            }
            else if (otherItem->GetIsContainer()) // Is it a quiver?
            {
                // Pick the first ammo we can shoot from the container
                // And set it as the active ammo
                bool bFound = false;
                for (size_t i=1; i<attacker_data->Inventory().GetInventoryIndexCount() && !bFound; i++)
                {
                    psItem* currItem = attacker_data->Inventory().GetInventoryIndexItem(i);
                    if (currItem && 
                        currItem->GetContainerID() == otherItem->GetUID() &&
                        weapon->GetAmmoTypeID().In(currItem->GetBaseStats()->GetUID()))
                    {
                        otherItem = currItem;
                        bFound = true;
                    }
                }
                if (!bFound)
                    attack_result = ATTACK_OUTOFAMMO;
            }
            else if (!weapon->GetAmmoTypeID().In(otherItem->GetBaseStats()->GetUID()))
            {
                attack_result = ATTACK_OUTOFAMMO;
            }

            if (attack_result != ATTACK_OUTOFAMMO)
            {
                psItem* usedAmmo = attacker_data->Inventory().RemoveItemID(otherItem->GetUID(), 1);
                if (usedAmmo)
                {
                    attack_result=CalculateAttack(event, usedAmmo);
                    usedAmmo->Destroy();
                    psserver->GetCharManager()->UpdateItemViews(attacker_client->GetClientNum());
                }
                else
                    attack_result=CalculateAttack(event);
            }
        }
        else
        {
            attack_result=CalculateAttack(event);
        }

        event->AttackResult=attack_result;

        ApplyCombatEvent(event, attack_result);
    }

    // Queue next event to continue combat if this is an auto attack slot
    if (attacker_data->Inventory().IsItemAutoAttack(event->GetWeaponSlot()))
    {
//      CPrintf(CON_DEBUG, "Queueing Slot %d for %s's next combat event.\n",event->GetWeaponSlot(), event->attacker->GetName() );
        QueueNextEvent(event);
    }
    else
    {
#ifdef COMBAT_DEBUG
        psserver->SendSystemError(event->AttackerCID, "Item %s is not a auto attack item.",attacker_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot())->GetName());
#endif
    }
//    else
//        CPrintf(CON_DEBUG, "Slot %d for %s not an auto-attack slot.\n",event->GetWeaponSlot(), event->attacker->GetName() );
}
コード例 #5
0
ファイル: advicemanager.cpp プロジェクト: garinh/planeshift
void AdviceManager::HandleAdviceRequest( Client *advisee, csString message )
{
    //    psserver->SendSystemInfo( advisee->GetClientNum(), "Sorry for the inconvenience, you cannot request advice right now. The advice system is under maintenaince and will be available after a server restart soon.");
    //    return;

    if ( advisee->GetAdvisor() )
    {
        psserver->SendSystemInfo( advisee->GetClientNum(), "You cannot request advice while you are an advisor. Lay down your advisor role using \"/advisor off\", then request advice.");
        return;
    }

    if ( advisors.GetSize() == 0 )                             //No advisors are online
    {
        //Send back an message that there is no advisor online
        psserver->SendSystemInfo( advisee->GetClientNum(),"The world has no advisors at the moment. You may ask for further help on IRC or on our forums. You may also try to ask players around you for help with \"/tell <player name> <message>\".");
        return;
    }

    // find existing Advicee in the List
    AdviceSession *activeSession = AdviseeList.Get(advisee->GetClientNum(), NULL);

    // Create an adviceSession if one doesn't exist and the message is valid
    if ( !activeSession )
    {
        WordArray words(message);
        // Check to make sure the request is 'good'
        if ( words.GetCount() < 2 )
        {
            psserver->SendSystemInfo( advisee->GetClientNum(),
                                     "An Advisor will need more information than this to help you, please include as much as you can in your request.");
            return;
        }

        Debug2( LOG_ANY, advisee->GetClientNum(), "Creating AdviceSession for %d", advisee->GetClientNum() );
        activeSession = new AdviceSession( this, NULL, advisee, message );
        AdviseeList.Put(activeSession->AdviseeClientNum, activeSession);  // Advice is no longer pending.
    }
    else
    {
        // One unadvised unanswered question at a time
        if (!activeSession->GetAdvisor() && !activeSession->answered)
        {
            psserver->SendSystemError(advisee->GetClientNum(), "Please wait for an advisor to respond to your previous inquiry before asking another question.");
            return;
        }
    }

    // Create psAdviceRequestTimeoutGameEvent to timeout question.
    if ( activeSession && activeSession->timeoutEvent == NULL && activeSession->requestEvent == NULL)
    {
        psAdviceRequestTimeoutGameEvent *ev = new psAdviceRequestTimeoutGameEvent( this, ADVICE_QUESTION_TIMEOUT, advisee->GetActor(), activeSession );
        activeSession->requestEvent = ev;
        psserver->GetEventManager()->Push(ev);
        activeSession->answered = false;
    }
    else if ( activeSession )
    {
        WordArray words(message);

        // Check to make sure the request is 'good'
        if ( words.GetCount() < 2 )
        {
            psserver->SendSystemInfo(advisee->GetClientNum(), "An Advisor will need more information than this to help you, please include as much as you can in your request.");
            activeSession->answered = true;
            return;
        }

        if ( activeSession->timeoutEvent )
        {
            activeSession->timeoutEvent->valid = false;
        }
        psAdviceSessionTimeoutGameEvent *ev = new psAdviceSessionTimeoutGameEvent( this, activeSession->answered?ADVICE_SESSION_TIMEOUT:ADVICE_SESSION_TIMEOUT/2, advisee->GetActor(), activeSession );
        activeSession->timeoutEvent = ev;
        psserver->GetEventManager()->Push(ev);
        activeSession->answered = false;
    }

    activeSession->lastRequest = message;

    csString buf;

    if ( activeSession->AdvisorClientNum != (uint32_t)-1 )
    {
        // Source Client Name, Target Client Name, Message
        buf.Format("%s, %s, \"%s\"", advisee->GetName(), activeSession->GetAdvisor()->GetActor()->GetName(), message.GetData() );
        psserver->GetLogCSV()->Write(CSV_ADVICE, buf);

        psChatMessage msgAdvisor( activeSession->AdvisorClientNum, 0, advisee->GetName(), 0, message , CHAT_ADVICE, false );
        msgAdvisor.SendMessage();

        // Send message to GM chars as well
        for (size_t i = 0; i < advisors.GetSize(); i++)
        {
            if (!advisors[i].GM || advisors[i].id == activeSession->AdvisorClientNum)
                continue;
            psChatMessage msgAdvisor( advisors[i].id, 0, advisee->GetName(), 0, message, CHAT_ADVICE, false);
            msgAdvisor.SendMessage();
        }
    }
    else
    {
        // Source Client Name, Target Client Name, Message
        buf.Format("%s, %s, \"%s\"", advisee->GetName(), "All Advisors", message.GetData() );
        psserver->GetLogCSV()->Write(CSV_ADVICE, buf);

        for (size_t i = 0; i < advisors.GetSize(); i++)
        {
            psChatMessage msgAdvisor( advisors[i].id, 0, advisee->GetName(), 0, message, CHAT_ADVICE, false);
            msgAdvisor.SendMessage();
        }
    }
    psChatMessage msgChat( advisee->GetClientNum() , 0, advisee->GetName(), 0, message, CHAT_ADVICE, false);
    msgChat.SendMessage();


}
コード例 #6
0
ファイル: devScaler_VS.c プロジェクト: A2-Collaboration/epics
/***************************************************
* scalerVS_arm()
* Make scaler ready to count.  If ARM output is connected
* to ARM input, and GATE permits, the scaler will
* actually start counting.
****************************************************/
STATIC long scalerVS_arm(scalerRecord *psr, int val)
{
	devScalerPvt *dpvt = psr->dpvt;
	int card = dpvt->card;
	volatile char *addr;
	volatile uint16 u16;
	int i, j, retry, read_again, numBad, numGood;

	Debug2(1, "scalerVS_arm: card %d, val %d\n", card, val);

	if (card >= scalerVS_total_cards) return(ERROR);
	addr = scalerVS_state[card]->localAddr;
	callbackGetUser(psr, scalerVS_state[card]->pcallback);

	/* disable end-of-gate interrupt */
	u16 = readReg16(addr,IRQ_SETUP_OFFSET);
	writeReg16(addr,IRQ_SETUP_OFFSET, u16 & 0x07ff);

	if (val) {
		/*** start counting ***/

		/* reset counters, overflows, and overflow-IRQ source */
		writeReg16(addr,RESET_ALL_COUNTERS_OFFSET, (uint16)1);
		/* clear other IRQ's */
		writeReg16(addr,CLEAR_INTERRUPT_2_3_OFFSET, (uint16)3);

		/** Set up and enable interrupts **/
		/* Write interrupt vector to hardware */
		writeReg16(addr,IRQ_3_GATE_VECTOR_OFFSET, (uint16)(vs_InterruptVector + card));
		Debug(10,"scalerVS_arm: irq vector=%d\n", (int)readReg16(addr,IRQ_3_GATE_VECTOR_OFFSET) & 0x00ff);

		/* set end-of-gate interrupt level, and enable the interrupt */
 		u16 = readReg16(addr, IRQ_SETUP_OFFSET);
		u16 = (u16 & 0x0ff) | (vs_InterruptLevel << 8) | 0x800;
		writeReg16(addr, IRQ_SETUP_OFFSET, u16);


		/*
		 * How do I make sure the internal-gate counter is zero, and that it
		 * won't start counting as soon as ARM goes TRUE?
		 */

		/* clear hardware-done flag */
		scalerVS_state[card]->done = 0;

		/* enable all channels */
		writeReg16(addr, COUNT_ENABLE_OFFSET, 1);	/* any write enables */

		/* arm scaler */
		writeReg16(addr, ARM_OFFSET, 1);	/* any write sets ARM */

		/* Make sure trigger mode is set for internal gate. */
		/* (This was already done in write_preset().  It's ok to do it again.) */
 		u16 = readReg16(addr, CLOCK_TRIG_MODE_OFFSET);
		writeReg16(addr, CLOCK_TRIG_MODE_OFFSET, u16 | 0x0010);

		/* trigger gate */
		if (devScaler_VS_check_trig) {
			for (i=0, retry=1; retry && i<devScaler_VS_trig_retries; i++) {
				writeReg16(addr, TRIG_GATE_OFFSET, 1); /* any write triggers gate */
				/*
				 * Check status register bit 9 to make sure internal gate is open.
				 * Repeat reading until we get the same value devScaler_VS_trig_reads
				 * times in a row.
				 */
				for (read_again = 1; read_again; ) {
					for (j=0, numBad=numGood=0; j<devScaler_VS_trig_reads; j++) {
						u16 = readReg16(addr, STATUS_OFFSET);
						if (u16 & 0x0200) numGood++; else numBad++;
					}
					if (numBad == devScaler_VS_trig_reads) {
						/* we believe the gate did NOT get triggered */
						retry = 1; read_again = 0;
					} else if (numGood == devScaler_VS_trig_reads) {
						/* we believe the gate got triggered */
						retry = 0; read_again = 0;
					}
				}
			}
			if (retry) {
				printf("scalerVS_arm: %d trigger attempts apparently failed\n", i);
			} else if (i >= devScaler_VS_trig_retry_report) {
				Debug(1,"scalerVS_arm: trigger succeeded after %d retries.\n", i);
			}
		} else {
			writeReg16(addr, TRIG_GATE_OFFSET, 1); /* any write triggers gate */
		}

		Debug2(5,"scalerVS_arm: gate open; SR=0x%x; irq vector=%d\n",
			readReg16(addr, STATUS_OFFSET),
			(int)readReg16(addr,IRQ_3_GATE_VECTOR_OFFSET) & 0x00ff);

	} else {
		/*** stop counting ***/
		/* disarm scaler */
		writeReg16(addr, DISARM_OFFSET, 1);	/* any write resets ARM */

		/*
		 * Stop counter (change trigger mode from internal gate to external gate
		 * (external gate should be 1?)
		 */
		u16 = readReg16(addr, CLOCK_TRIG_MODE_OFFSET);
		writeReg16(addr, CLOCK_TRIG_MODE_OFFSET, u16 & 0x000f);

		/* set hardware-done flag */
		scalerVS_state[card]->done = 1;

	}

	return(0);
}
コード例 #7
0
ファイル: devScaler_VS.c プロジェクト: A2-Collaboration/epics
/***************************************************
* scalerVS_write_preset()
* This hardware has no preset capability, but we can set a time gate.
* What we do here is put the hardware in "trigger" mode, set the gate-clock
* frequency and the number of gate-clock periods to count for.  We're going to
* get called once for each channel, but we do all the real work on the first call.
* From then on, we just make sure the presets are zero, and fix them if they aren't.
****************************************************/
STATIC long scalerVS_write_preset(scalerRecord *psr, int signal, long val)
{
 	devScalerPvt *dpvt = psr->dpvt;
	int card = dpvt->card;
	epicsInt32 *ppreset;
	unsigned short *pgate;
	volatile char *addr;
	unsigned short gate_freq_ix;
	double gate_time, gate_freq, gate_periods;

	if (devScaler_VSDebug >= 5) {
		printf("%s(%d):",__FILE__,__LINE__);
		printf("scalerVS_write_preset: card %d, signal %d, val %ld\n", card, signal, val);
	}

	if (card >= scalerVS_total_cards) return(ERROR);
	if (signal >= MAX_SCALER_CHANNELS) return(ERROR);

	addr = scalerVS_state[card]->localAddr;
	callbackGetUser(psr, scalerVS_state[card]->pcallback);

	if (signal > 0) {
		if (val != 0) {
			ppreset = &(psr->pr1);
			ppreset[signal] = 0;
			db_post_events(psr,&(ppreset[signal]),DBE_VALUE);
			pgate = &(psr->g1);
			pgate[signal] = 0;
			db_post_events(psr,&(pgate[signal]),DBE_VALUE);
		}
		return(0);
	}

	if (psr->g1 != 1) {
		psr->g1 = 1;
		db_post_events(psr,&(psr->g1),DBE_VALUE);
	}

	/*** set count time ***/
	gate_time = val / psr->freq;
	/*
	 * find largest gate-clock frequency that will allow us to specify the
	 * requested count time with the 16-bit gate-preset register.  Note that
	 * the scaler counts for one extra clock cycle, so we allow 0xffff + 1
	 * = 65536 cycles.
	 */
	gate_freq_ix = 0;
	do {
		gate_freq = gate_freq_table[gate_freq_ix];
		gate_periods =  gate_time * gate_freq;
		if (devScaler_VSDebug >= 10) {
		        printf("%s(%d):",__FILE__,__LINE__);
			printf("scalerVS_write_preset: try f=%.0f, n=%.0f, ix=%d\n",
				gate_freq, gate_periods, gate_freq_ix);	
		}
	} while ((gate_periods > 65536) && (++gate_freq_ix < GATE_FREQ_TABLE_LENGTH));

	if ((gate_periods < 4) && (gate_freq_ix == 0)) {
		/* The scaler can't count this short.  Just count as short as possible */
		printf("devScaler_VS: min. counting time is 4E-7 seconds.\n");
	}

	/* docs recommend min of 4 periods; we're going to subtract 1 before writing. */
	if (gate_periods < 5) gate_periods = 5;

	if ((gate_periods > 65536) && (gate_freq_ix >= GATE_FREQ_TABLE_LENGTH)) {
		/* The scaler can't count this long.  Just count as long as possible */
		printf("devScaler_VS: max. counting time is 655.36 seconds.\n");
		gate_periods = 65536;
		gate_freq_ix = GATE_FREQ_TABLE_LENGTH - 1;
	}

	/* set clock frequency, and specify that software should trigger gate-start */
	writeReg16(addr, CLOCK_TRIG_MODE_OFFSET, gate_freq_bits[gate_freq_ix] | 0x10);

	/* Set the gate-size register to the number of clock periods to count. */
	/* Scaler must be in trigger mode at the time gate size is written. */
	/* Docs say to specify (desired_clock_periods - 1) */
	writeReg16(addr, INTERNAL_GATE_SIZE_OFFSET, (uint16)(gate_periods-1));

	/* save preset and frequency mask in scalerVS_state */
	scalerVS_state[card]->gate_periods = gate_periods;
	scalerVS_state[card]->gate_freq_ix = gate_freq_ix;

	/* tell record what preset and clock rate we're using  */
	psr->pr1 = gate_periods;
	psr->freq = gate_freq_table[gate_freq_ix];

	Debug2(10,"scalerVS_write_preset: gate_periods=%f, gate_freq=%f\n",
		gate_periods, gate_freq);

	return(0);
}
コード例 #8
0
void pawsNpcDialogWindow::HandleMessage(MsgEntry* me)
{
    if(me->GetType() == MSGTYPE_DIALOG_MENU)
    {
        psDialogMenuMessage mesg(me);

        Debug2(LOG_QUESTS, 0,"Got psDialogMenuMessage: %s\n", mesg.xml.GetDataSafe());
        responseList->Clear();

        SelfPopulateXML(mesg.xml);

        if(useBubbles)
        {
            speechBubble->Hide(); // hide previous npc say response
            LoadQuest(mesg.xml);
            AdjustForPromptWindow(); // should be done before DisplayQuestBubbles
            DisplayQuestBubbles(displayIndex);
            gotNewMenu = true;
        }
        else
        {
            AdjustForPromptWindow();
        }

        Show();
    }
    else if(me->GetType() == MSGTYPE_CHAT)
    {
        psChatMessage chatMsg(me);
        Debug2(LOG_QUESTS, 0,"Got Chat message from NPC: %s\n", (const char*)chatMsg.sText);

        GEMClientActor* actor = dynamic_cast<GEMClientActor*>(psengine->GetCelClient()->FindObject(chatMsg.actor));
        if(!actor)
            return;

        // handle the basic action types, in the future we could play an animation as well
        csString inText ;
        switch(chatMsg.iChatType)
        {
            case CHAT_NPC_ME:
            {
                inText.Format("(%s %s)", (const char*)chatMsg.sPerson, ((const char*)chatMsg.sText));
                break;
            }

            case CHAT_NPC_MY:
            {
                inText.Format("(%s's %s)", (const char*)chatMsg.sPerson, ((const char*)chatMsg.sText));
                break;
            }

            case CHAT_NPC_NARRATE:
            {
                inText.Format("(%s)", (const char*)chatMsg.sText);
                break;
            }
            default:
                inText = chatMsg.sText;
        }
        NpcSays(inText, actor);

        //checks if the NPC Dialogue is displayed, in this case don't show the normal overhead bubble
        if(IsVisible())
            return;
    }
    else if(me->GetType() == MSGTYPE_REMOVE_OBJECT)
    {
        psRemoveObject mesg(me);
        //if the current target is being removed hide this window
        if(IsVisible() && targetEID.IsValid() && mesg.objectEID.IsValid() && mesg.objectEID == targetEID)
        {
            Hide();
            //In these cases something might have gone wrong with the camera
            //eg: the character is being teleported. So we need to have it reset
            //correctly.
            psengine->GetPSCamera()->ResetCameraPositioning();
        }
    }
}
コード例 #9
0
void pawsNpcDialogWindow::OnListAction(pawsListBox* widget, int status)
{
    if(status == LISTBOX_HIGHLIGHTED)
    {
        pawsTextBox* fld = dynamic_cast<pawsTextBox*>(widget->GetSelectedRow()->FindWidgetXMLBinding("text"));
        Debug2(LOG_QUESTS, 0, "Pressed: %s\n",fld->GetText());
    }
    else if(status == LISTBOX_SELECTED)
    {
        //if no row is selected
        if(!widget->GetSelectedRow())
            return;

        pawsTextBox* fld  = dynamic_cast<pawsTextBox*>(widget->GetSelectedRow()->FindWidgetXMLBinding("text"));
        Debug2(LOG_QUESTS, 0,"Player chose '%s'.\n", fld->GetText());
        pawsTextBox* trig = dynamic_cast<pawsTextBox*>(widget->GetSelectedRow()->FindWidgetXMLBinding("trig"));
        Debug2(LOG_QUESTS, 0,"Player says '%s'.\n", trig->GetText());

        csString trigger(trig->GetText());

        // Send the server the original trigger
        csString cmd;
        if(trigger.GetAt(0) == '=')  // prompt window signal
        {
            // cut the questID and convert it to a number as it's needed by the prompt window management
            size_t pos = trigger.FindFirst("{");
            size_t endPos = trigger.FindFirst("}");
            int questID = -1;
            if(pos != SIZET_NOT_FOUND)
            {
                unsigned long value = strtoul(trigger.GetData() + pos + 1, NULL, 0);
                questID = value;
                // check for overflows
	    		if(questID < -1) 
    			{
                    questID = -1;
                }

                endPos += 1;
            }
            else
            {
                endPos = 1;
            }

            pawsStringPromptWindow::Create(csString(trigger.GetData()+endPos),
                                           csString(""),
                                           false, 320, 30, this, trigger.GetData()+endPos, questID);
        }
        else
        {
            if(trigger.GetAt(0) != '<')
            {
                cmd.Format("/tellnpc %s", trigger.GetData());
                psengine->GetCmdHandler()->Publish(cmd);
            }
            else
            {
                psSimpleStringMessage gift(0,MSGTYPE_EXCHANGE_AUTOGIVE,trigger);
                gift.SendMessage();
            }
            DisplayTextInChat(fld->GetText());
        }
        Hide();
    }
}